Skip to content
第05回 プレイヤーを狙う敵弾

3 / 4 敵の発射処理とタイマー制御 ​

このステップの目的

敵に発射タイマーを持たせ、目標となるプレイヤー座標を渡して敵弾の生成を依頼する処理を実装します。

敵の発射間隔とタイマーの管理 ​

敵もプレイヤーと同じく、毎フレーム無制限に撃たず、一定間隔で射撃します。
第02回のTryShootと同様に、発射できる時刻かを調べてから弾の生成を依頼します。

まずEnemy.hのdxgame::shooting名前空間で、Enemyクラスの手前へclass EnemyShotManager;を追加してください。続いて、同クラスのpublicとprivateに以下を追加します。

Enemy.hcpp
public:
    // 発射間隔を確認し、目標位置へ向けて敵弾を発射できたらtrueを返す
    bool TryShoot(EnemyShotManager& shots, const Vector2& targetPosition);

private:
    Vector2 GetMuzzlePosition() const;

    // 次の発射までの残り時間(秒)
    float shotTimer = 0.0f;

Enemy.cppでは既存のインクルードに次を追加します。

Enemy.cppcpp
#include "Shooting/Tuning/GameTuning.h"
#include "Shooting/EnemyShotManager.h"

Spawn()でageを初期化する行の下に、最初の発射までの待ち時間ShotDelayを設定します。2発目以降の間隔にはShotIntervalを使います。使用する前に、GameTuning.hのnamespace enemyへ2つの定数を追加してください。

GameTuning.h(namespace enemy内)cpp
    inline constexpr float SpawnDelay = 0.40f;
    inline constexpr float ShotDelay = 0.80f;
    inline constexpr float ShotInterval = 1.80f;
Enemy.cpp(Spawn内)cpp
    age = 0.0f;
    shotTimer = tuning::enemy::ShotDelay;
    hp = tuning::enemy::MaxHp;

Enemy.cppの同じ名前空間内へ、発射する関数を追加します。

Enemy.cppcpp
bool Enemy::TryShoot(EnemyShotManager& shots, const Vector2& targetPosition)
{
    if (!isActive || shotTimer > 0.0f)
        return false;

    if (!shots.Spawn(GetMuzzlePosition(), targetPosition))
        return false;

    shotTimer = tuning::enemy::ShotInterval;
    return true;
}

プールが満杯で弾を生成できなければ、タイマーはリセットしません。空きができたら、すぐに発射を試みます。

タイマーの減算と銃口位置 ​

Enemy::Update()内で、毎フレームdeltaTime分だけタイマーを減算します。

Enemy.cpp の Update に追加cpp
age += deltaTime;
shotTimer -= deltaTime;
position.y += moveSpeed * deltaTime;

敵弾は機体の下側から出るほうが自然に見えるため、中心から下方向(+Y方向)へずらした位置を銃口にします。

Enemy.cppcpp
Vector2 Enemy::GetMuzzlePosition() const
{
    Rect hitbox = GetHitbox();

    return
    {
        hitbox.GetCenter().x,
        hitbox.y + hitbox.height + tuning::enemyShot::Hitbox.height * 0.5f
    };
}

Gameから敵へ目標位置を渡す ​

Gameは、前回の命中判定で使ったEnemyManager::GetAll()で敵を順に取り出します。Player::GetHitbox().GetCenter()で求めた自機の中心を、各EnemyのTryShoot()へ渡します。次のステップでGame::Update()へ接続します。

チェックリスト
  • 敵が自身の発射タイマーshotTimerを独立して管理している
  • 弾の生成に成功した場合のみタイマーがリセットされている
  • 出現時の待ち時間と、発射後の待ち時間を設定する場所を区別できる
  • 銃口位置が機体の下端になることを式から確認できる(画面での確認は次のステップで行う)