第06回 プレイヤーの被弾と無敵時間
3 / 4 敵弾および敵本体との接触判定
このステップの目的
敵弾や敵本体がプレイヤーに接触したことを検知し、共通の被弾処理へ安全に接続します。
敵弾とプレイヤーの命中調停
Game::ResolveCollisions()に、敵弾とプレイヤーの当たり判定を追加します。
Game.cppcpp
// 敵弾とプレイヤーの命中判定
for (EnemyShot& enemyShot : enemyShots.GetAll())
{
if (!enemyShot.IsActive())
continue;
// プレイヤーの命中矩形と重なっているか判定
if (!enemyShot.GetHitbox().Overlaps(player.GetHitbox()))
continue;
// 命中した敵弾を直ちに消滅させる
enemyShot.Deactivate();
// プレイヤーに被弾を依頼する
if (player.TryTakeDamage())
{
// 被弾成立時の処理(後続回で効果音やエフェクトを追加する位置)
}
}無敵時間中でも敵弾を消滅させる理由
player.TryTakeDamage()の結果にかかわらず、接触した敵弾を必ずenemyShot.Deactivate()で消す点に注目してください。
無敵時間中に敵弾を消さずに残すと、機体に重なったままになり、無敵時間が切れたときに連続して大きなダメージを受けます。接触した弾をすぐに消すと、公平で自然な動きになります。
敵本体とプレイヤーの接触判定
シューティングゲームでは、敵の弾だけでなく敵の機体そのものに激突(体当たり)した際もダメージを受けます。
敵本体との接触も、敵弾とまったく同じPlayer::TryTakeDamage()を利用して調停します。
Game.cppcpp
// 敵本体とプレイヤーの接触判定
for (Enemy& enemy : enemies.GetAll())
{
if (!enemy.IsActive())
continue;
if (!enemy.GetHitbox().Overlaps(player.GetHitbox()))
continue;
// 接触した敵を停止させる
enemy.Deactivate();
// プレイヤーにダメージを適用する
player.TryTakeDamage();
}接触した敵は、すぐにenemy.Deactivate()で停止させます。同じ敵と何度も接触判定が行われる不具合を防げます。
第04回の「プレイヤー弾と敵」に、今回の「敵弾とプレイヤー」「敵本体とプレイヤー」の2つのループを加えます。これで、オブジェクト間の相互作用をすべてGame::ResolveCollisions()で扱えます。
チェックリスト
- 敵弾がプレイヤーに接触した瞬間に敵弾が消滅することを確認できる
- 敵本体と接触した場合も敵が消滅し、プレイヤーに被弾処理が適用されることを確認できる
- 無敵時間中に接触しても敵弾が消費され、無敵終了時の理不尽な連続ダメージが防がれている
- 第04回の自機弾による敵撃破処理を維持したまま、被弾処理が正しく追加されている