Skip to content

第05回 弾を撃つ

前回: 第04回 構造体と矩形 / 次回: 第06回 敵と衝突判定

今回の授業内容

  • 弾を表す構造体を追加する
  • 固定配列で複数の弾を管理する
  • 有効フラグで使用中と空きを区別する
  • ショットキーで弾を発射する
  • 画面外へ出た弾を無効化して再利用する

今回の開始状態

第04回終了時点では、プレイヤーが移動し、当たり判定の矩形を確認できます。
今回の終了時点では、ZまたはSpaceで弾を撃てるようにします。

まだBulletクラスは作りません。
第05回では、Game内に弾用の構造体と配列を置いて、まず固定配列管理の流れを理解します。

変更するファイル

ファイル変更内容
Game.hBullet構造体、弾配列、連射間隔を追加する
Game.cpp発射、更新、描画、無効化を追加する

弾のデータを用意する

Game.hに、弾を表す構造体を追加します。

cpp
struct Bullet
{
    Vec2 position;
    float speed;
    bool active;
};

続けて、Gameクラスに弾の配列を追加します。

cpp
static constexpr int maxBullets = 48;
Bullet bullets[maxBullets] = {};
int shotCooldown = 0;

配列の要素は最初から48個あります。
画面上で使っている弾だけをactive == trueとして扱います。

弾を発射する

Update()の中で、ショットキーが押されていて、連射待ちが終わっているかを確認します。

cpp
if ((input.IsDown(KEY_INPUT_Z) || input.IsDown(KEY_INPUT_SPACE)) && shotCooldown <= 0)
{
    SpawnBullet();
    shotCooldown = 8;
}

if (shotCooldown > 0)
    --shotCooldown;

SpawnBullet()では、空いている弾を探して初期値を入れます。

cpp
void Game::SpawnBullet()
{
    for (Bullet& bullet : bullets)
    {
        if (!bullet.active)
        {
            bullet.position = { playerPosition.x, playerPosition.y - 22.0f };
            bullet.speed = 8.0f;
            bullet.active = true;
            return;
        }
    }
}

空きがない場合は何も発射しません。
これは不具合ではなく、同時に出せる弾の上限に達したという仕様です。

弾を更新して描画する

更新では、使っていない弾を飛ばし、使っている弾だけ上へ動かします。

cpp
for (Bullet& bullet : bullets)
{
    if (!bullet.active)
        continue;

    bullet.position.y -= bullet.speed;

    if (bullet.position.y < -16.0f)
        bullet.active = false;
}

描画も同じように、activeな弾だけを描きます。

cpp
for (const Bullet& bullet : bullets)
{
    if (!bullet.active)
        continue;

    DrawBox(
        static_cast<int>(bullet.position.x - 3),
        static_cast<int>(bullet.position.y - 10),
        static_cast<int>(bullet.position.x + 3),
        static_cast<int>(bullet.position.y + 10),
        yellow,
        TRUE
    );
}

動作確認

  1. ZまたはSpaceで弾が出ることを確認する
  2. 弾が上方向へ移動することを確認する
  3. 画面外へ出た弾が消えることを確認する
  4. maxBullets3へ変更し、画面内に3発残っている間は新しい弾が出ないことを確認する
  5. 確認後、maxBullets48へ戻す

よくある問題

  • 弾が1発しか出ない場合は、空き弾を探すループとactiveの切り替えを確認する
  • 弾が消えない場合は、画面外でactive = falseに戻しているか確認する
  • 連射が速すぎる場合は、shotCooldownの値を確認する

今回の完成条件

  • 固定配列で複数の弾を管理できる
  • 有効フラグの役割を説明できる
  • ショットキーで弾を発射できる
  • 画面外へ出た弾を無効化できる

まとめ

今回は、固定配列と有効フラグで複数の弾を扱いました。
次回は敵を追加し、弾との衝突でスコアを増やします。