Appearance
第04回 プレイヤーの弾と敵の命中判定
2 / 4 命中した弾と敵を停止する
このステップの目的
命中した組み合わせを見つけ、弾と敵それぞれの責任へ処理を依頼する
先にEnemyへHPとダメージ処理を追加する
命中した敵を停止させる前に、Enemy自身がHPを持ち、ダメージを受けた結果として停止できるようにします。 第04回の開始コードにはこの処理がまだないため、次の3か所を追加します。
まず、GameTuning.hへ敵の最大HPとプレイヤー弾の攻撃力を追加します。
GameTuning.hcpp
namespace playerShot
{
inline constexpr int Damage = 1;
}
namespace enemy
{
inline constexpr int MaxHp = 1;
}次に、Enemy.hへHPとダメージ処理を追加します。
Enemy.hへ追加する宣言cpp
public:
void TakeDamage(int damage);
private:
int hp = 0;Enemy.cppのSpawn()でHPを最大値へ戻し、TakeDamage()で0以下になったら停止させます。
Enemy.cppのSpawnへ追加cpp
hp = tuning::enemy::MaxHp;Spawn()の既存処理は残したまま、isActive = true;と同じ初期化処理のまとまりへ追加します。
Enemy.cppへ追加する関数cpp
void Enemy::TakeDamage(int damage)
{
hp -= damage;
if (hp <= 0)
Deactivate();
}ここまでで、敵自身が「HPを減らす」「HPがなくなったら停止する」責任を持ちます。
Gameが相互作用を調停する
PlayerShotは敵の一覧を知りません。 Enemyもプレイヤー弾の一覧を知りません。 両方のManagerを知っているGameが、どの弾とどの敵を比較するかを決めます。
Game.cppでは、tuning::playerShot::Damageを使うため、includeへ次の1行を追加します。
Game.cppcpp
#include "Shooting/Tuning/GameTuning.h"Game.cppcpp
for (PlayerShot& playerShot : playerShots.GetAll())
{
if (!playerShot.IsActive())
continue;
for (Enemy& enemy : enemies.GetAll())
{
if (!enemy.IsActive())
continue;
if (!playerShot.GetHitbox().Overlaps(enemy.GetHitbox()))
continue;
enemy.TakeDamage(tuning::playerShot::Damage);
playerShot.Deactivate();
break;
}
}同じ弾を一度だけ命中させる
弾が敵へ命中したら、その弾を停止し、内側のループをbreakします。 これにより、同じフレームに同じ弾が複数の敵へ命中することを防ぎます。
敵のHPが0以下になったかどうかは、追加したEnemy::TakeDamage()が敵自身の状態として処理します。
チェックリスト
-
Gameが命中判定の組み合わせを調停している - 命中後に弾を
Deactivate()している - 1発の弾が1フレーム中に1体だけへ命中する