Skip to content
第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.cppSpawn()で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体だけへ命中する