Skip to content

第06回 敵と衝突判定

前回: 第05回 弾を撃つ / 次回: 第07回 クラス分割入門

今回の授業内容

  • 敵を表す構造体を追加する
  • 固定配列で複数の敵を生成する
  • 弾と敵の矩形で衝突判定を行う
  • 敵撃破でスコアを増やす
  • プレイヤーと敵の衝突でHPを減らす

今回の開始状態

第05回終了時点では、プレイヤーが弾を撃てます。
今回の終了時点では、敵が一定間隔で出現し、弾で倒せるようにします。

まだEnemyクラスは作りません。
弾と同じように、まずはGame内の構造体と配列で実装します。

変更するファイル

ファイル変更内容
Game.hEnemy構造体、敵配列、スコア、HP、フレーム数を追加する
Game.cpp敵生成、敵更新、衝突判定、UI表示を追加する
Collision.h第04回のIsOverlapping()を利用する

敵のデータを追加する

Game.hに敵を表す構造体と配列を追加します。

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

static constexpr int maxEnemies = 24;
Enemy enemies[maxEnemies] = {};
int frame = 0;
int score = 0;
int playerHp = 3;

frameは、敵を一定間隔で出現させるために使います。

敵を出現させる

Update()の先頭でframeを増やし、36フレームごとに敵を出します。

cpp
++frame;

if (frame % 36 == 0)
    SpawnEnemy();

SpawnEnemy()では、空いている敵を探して初期位置を入れます。

cpp
void Game::SpawnEnemy()
{
    const int lane = GetRand(7);
    const float x = 64.0f + lane * 72.0f;

    for (Enemy& enemy : enemies)
    {
        if (!enemy.active)
        {
            enemy.position = { x, -24.0f };
            enemy.speed = 2.0f;
            enemy.active = true;
            return;
        }
    }
}

敵の更新では、下方向へ移動し、画面外へ出たら無効化します。

cpp
for (Enemy& enemy : enemies)
{
    if (!enemy.active)
        continue;

    enemy.position.y += enemy.speed;

    if (enemy.position.y > screenHeight + 40.0f)
        enemy.active = false;
}

弾と敵の衝突を調べる

弾と敵の矩形を作り、IsOverlapping()で重なりを調べます。
この時点ではクラスの関数ではなく、ループ内で矩形を作ります。

cpp
Rect enemyRect = { enemy.position.x - 16.0f, enemy.position.y - 16.0f, 32.0f, 32.0f };
Rect bulletRect = { bullet.position.x - 4.0f, bullet.position.y - 10.0f, 8.0f, 20.0f };

衝突したら、敵と弾を無効化し、スコアを増やします。

cpp
if (IsOverlapping(enemyRect, bulletRect))
{
    enemy.active = false;
    bullet.active = false;
    ++score;
    break;
}

プレイヤーと敵の衝突では、敵を消してHPを減らします。
HPが0になった後のゲームオーバー処理は、第09回で状態として整理します。

動作確認

  1. 敵が上から出現して下へ移動することを確認する
  2. 弾が敵に当たると敵と弾が消えることを確認する
  3. スコアが1増えることを確認する
  4. プレイヤーと敵が当たるとHPが減ることを確認する
  5. frame % 36の値を変えて、出現間隔の違いを比較する

よくある問題

  • 敵が出ない場合は、frameを毎フレーム増やしているか確認する
  • スコアが一度に複数増える場合は、衝突後にbreakしているか確認する
  • 消えた敵にさらに当たる場合は、activeの確認位置を見直す

今回の完成条件

  • 敵を固定配列で複数管理できる
  • 一定間隔で敵を出現させられる
  • 弾と敵の衝突でスコアを増やせる
  • プレイヤーと敵の衝突でHPを減らせる

まとめ

今回は、敵、衝突、スコア、HPを追加しました。
次回は、長くなってきた処理をPlayerBulletEnemyのクラスへ分けます。