第3回:プレイヤーから弾を発射する
プレイヤーから敵を破壊するための弾を発射するには、発射ボタン(ここではスペースキー、あるいはゲームパッドの1ボタン)が押されたときに、プレイヤーがいる場所を初期位置として弾クラスをタスクに追加するとよいでしょう。CCharactorの派生となるCPlayerBulletクラスを作成します。このクラスはCPlayerクラスが記述されているソースコードファイル内に併記しても問題ありません。クラス作成時に渡す初期パラメータは発射位置の座標だけでも事足りるのですが、今回は3方向に弾が発射される3way弾も実装しようと思いますので、発射角度もパラメータとして用意しています。
プレイヤーの弾はゲーム中に数百発単位で発射されるため、CPlayerBulletが作成されるたびにFindObjectで弾のテクスチャクラスを検索するのは効率が悪いため、アイテムボックス(ハッシュクラス)に格納したものを呼び出すようにしましょう。
#define BULLET_PRIORITY 55000
class CPlayerBullet : public CCharactor
{
public:
CPlayerBullet(float sx, float sy, float moveangle);
private:
float angle;
protected:
virtual void Init();
virtual void Exec();
};
CPlayerBullet::CPlayerBullet(float sx, float sy, float moveangle)
{
x = sx;
y = sy;
angle = moveangle;
}
void CPlayerBullet::Init()
{
sprite.SetTexture((CTexture*)FindItemBox("pbullet"));
}
void CPlayerBullet::Exec()
{
const float move = 8.0f;
float mx = move * sinf(angle);
float my = move * cosf(angle);
x += mx;
y -= my;
if(y < -16.0f){
RemoveObject(this);
return;
}
sprite.Draw(x, y, angle);
}

この問題を解決するため、ボタンを押しっぱなしでオート連射が行えるようにプログラミングしましょう。以下のプログラムコードでは、ボタンが押しっぱなしの場合は、数フレーム毎に1回ボタン入力を受け付けることにし、ボタン連打による連射時はボタン入力を受け付けるフレーム間隔を短くすることで、連打による連射のメリットが享受できるようにしています。
class CPlayer : public CCharactor
{
/* 省略 */
private:
int shoottime; // 最後に発射されてからの時間
void Shoot();
};
void CPlayer::Init()
{
/* 省略 */
missile = *(CSound*)FindItemBox("missile");
shoottime = 0;
}
void CPlayer::Exec()
{
/* 省略 */
// ↓追加するプログラムコード
if(shoottime > 10 && (input->IsKeyDown(DIK_SPACE) || input->IsButtonDown(0)))
{
// 最後の発射から10フレーム経っていれば
// オート連射の入力を受け付ける
Shoot();
shoottime = 0;
}
else if(shoottime > 5 && (input->IsKeyPressed(DIK_SPACE) || input->IsButtonPressed(0)))
{
// 最後の発射から5フレーム経っていれば
// マニュアル連射の入力を受け付ける
Shoot();
shoottime = 0;
}else{
shoottime++;
}
sprite.Draw(x, y);
}
void CPlayer::Shoot()
{
AppendObject(new CPlayerBullet(x, y - 8.0f, d2r(0.0f)), BULLET_PRIORITY, true);
}
game.AppendObject(new CPlayer(), PLAYER_PRIORITY, true);
// ↓弾のテクスチャデータを追加
CTexture *bullettex = new CTexture(_T("data\\pbullet.png"));
game.AppendItemBox("pbullet", bullettex);
game.AppendObject(bullettex, 1000, true);
ShowWindow(mainWnd, nCmdShow);