2 / 4 命中した弾と敵の処理
弾が敵に命中したときの処理をまとめ、敵の耐久力を減らして弾を消す仕組みを実装します。
敵に耐久力とダメージ処理を追加する
敵へ弾が当たったら、耐久力(HP)を減らします。まずHPを1、弾の攻撃力を1にして、1発で敵が消える処理を作ります。
敵の最大HPとプレイヤー弾の攻撃力は、調整しやすいようにGameTuning.hへ定義します。
namespace playerShot
{
// プレイヤー弾の攻撃力
inline constexpr int Damage = 1;
}
namespace enemy
{
// 敵の最大耐久力(HP)
inline constexpr int MaxHp = 1;
}続いて、敵を表すEnemyクラスにHPを保持するメンバ変数と、ダメージを受けるメンバ関数TakeDamage()を宣言します。
public:
// 指定ダメージを受け、HPが0以下になったら停止する
void TakeDamage(int damage);
private:
int hp = 0;敵が出現する際、HPを初期最大値へ設定します。Enemy.cppのSpawn()内で、調整値tuning::enemy::MaxHpを代入します。
void Enemy::Spawn(const Vector2& startPosition, float speed, Behaviour spawnBehaviour)
{
position = startPosition;
baseX = startPosition.x;
moveSpeed = speed;
age = 0.0f;
hp = tuning::enemy::MaxHp;
behaviour = spawnBehaviour;
isActive = true;
}TakeDamage()では、受け取ったダメージ分だけhpを減らします。HPが0以下になったら、Deactivate()で敵を停止させます。
void Enemy::TakeDamage(int damage)
{
hp -= damage;
if (hp <= 0)
Deactivate();
}HPの変更と停止の判断をEnemyにまとめると、呼び出す側は与えるダメージだけを指定できます。
Gameから弾と敵へ処理を依頼する
Gameは弾と敵の両方を所有しています。両者の矩形を調べ、重なっていれば敵にダメージを与え、弾を停止させます。
Gameクラスでは、有効なプレイヤー弾と敵のすべての組み合わせを調べます。矩形が重なっていれば、弾と敵それぞれに命中後の処理を行わせます。
プレイヤー弾の攻撃力定数を使用するため、Game.cppのインクルードにGameTuning.hを追加したうえで、衝突解決を行うResolveCollisions()を実装します。
#include "Shooting/Game.h"
#include "Shooting/Tuning/GameTuning.h"Game.hのprivate内で、Draw()の宣言の下へ次の宣言を追加します。その後、Game.cppのdxgame::shooting名前空間内へ関数を定義します。
void Draw() const;
void ResolveCollisions();void Game::ResolveCollisions()
{
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;
}
}
}Game::Update()で敵を移動した後、プレイヤーが次の弾を発射する前に呼び出します。ここまで編集したらビルドして実行し、弾が当たると敵と弾が消えることを確認します。得点は次のステップで追加します。
enemies.Update(deltaTime);
ResolveCollisions();
player.TryShoot(input, playerShots);1発の弾が複数の敵へ貫通することを防ぐ
この二重ループでは、命中直後のplayerShot.Deactivate()とbreakが重要です。
弾が敵Aに命中した後も内側のループを続けると、同じフレームで近くや背後の敵Bとも命中判定を行います。通常弾が意図せず貫通しないよう、弾を停止させた直後にbreakで内側のループを抜けます。
これで、1発の通常弾が命中する敵を最大1体に制限できます。
- 敵自身がHPの保持およびダメージ時の停止処理を担当している
-
Gameクラスが仲介役として弾と敵の命中判定を調停している - 弾が敵に命中した直後に
breakし、同フレーム内に複数体へ貫通しないよう制御できている