Appearance
第06回 敵と衝突判定
前回: 第05回 弾を撃つ / 次回: 第07回 クラス分割入門
今回の授業内容
- 敵を表す構造体を追加する
- 固定配列で複数の敵を生成する
- 弾と敵の矩形で衝突判定を行う
- 敵撃破でスコアを増やす
- プレイヤーと敵の衝突でHPを減らす
今回の開始状態
第05回終了時点では、プレイヤーが弾を撃てます。
今回の終了時点では、敵が一定間隔で出現し、弾で倒せるようにします。
まだEnemyクラスは作りません。
弾と同じように、まずはGame内の構造体と配列で実装します。
変更するファイル
| ファイル | 変更内容 |
|---|---|
Game.h | Enemy構造体、敵配列、スコア、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増えることを確認する
- プレイヤーと敵が当たるとHPが減ることを確認する
frame % 36の値を変えて、出現間隔の違いを比較する
よくある問題
- 敵が出ない場合は、
frameを毎フレーム増やしているか確認する - スコアが一度に複数増える場合は、衝突後に
breakしているか確認する - 消えた敵にさらに当たる場合は、
activeの確認位置を見直す
今回の完成条件
- 敵を固定配列で複数管理できる
- 一定間隔で敵を出現させられる
- 弾と敵の衝突でスコアを増やせる
- プレイヤーと敵の衝突でHPを減らせる
まとめ
今回は、敵、衝突、スコア、HPを追加しました。
次回は、長くなってきた処理をPlayer、Bullet、Enemyのクラスへ分けます。