Skip to content
第03回 敵の出現と移動

2 / 4 レーンとタイマーで敵を出現させる

このステップの目的

画面上端の決められたレーンから、一定間隔で敵を再利用して出現させる

出現位置を設定値にする

敵の出現位置をGame.cppへ直接書かず、GameTuning.hの設定値から計算します。 画面幅に合わせてレーン数や間隔を変更しても、出現処理の流れを変えずに済みます。

GameTuning.hcpp
inline constexpr int LaneCount = 8;
inline constexpr float LaneStart = 64.0f;
inline constexpr float LaneSpacing = 72.0f;

出現順をレーン数で割った余りに変換すると、左から右へ進んだ後、再び最初のレーンへ戻せます。 敵の配列の添字と画面上のレーン番号を同じものとして扱わないことがポイントです。

出現タイマーをManagerへ持たせる

出現間隔を測るタイマーと出現順は、敵全体の処理を担当するEnemyManagerが持ちます。 敵1体が自分の出現タイミングを判断するのではありません。

EnemyManager.hcpp
std::array<Enemy, Capacity> enemies = {};
float spawnTimer = 0.0f;
int spawnIndex = 0;

タイマーが0以下になったら、停止中の要素を1体選んでSpawn()を呼び出します。 出現後は次の間隔を設定し、出現順を1つ進めます。

処理の順番は次の形に固定します。まず敵を更新し、次に出現タイマーを進め、必要なときだけ空き要素へ生成を依頼します。

EnemyManager.cppcpp
void EnemyManager::Update(float deltaTime)
{
    for (Enemy& enemy : enemies)
        enemy.Update(deltaTime);

    spawnTimer -= deltaTime;
    if (spawnTimer <= 0.0f)
    {
        SpawnOne();
        spawnTimer = tuning::enemy::SpawnInterval;
    }
}

SpawnOne()の中では、最初に見つかった停止中の敵へ、レーンから計算した位置を渡します。 空きがない場合は何も生成せず、次のタイミングで再び試します。

EnemyManager.cppcpp
void EnemyManager::SpawnOne()
{
    for (Enemy& enemy : enemies)
    {
        if (enemy.IsActive())
            continue;

        int lane = spawnIndex % tuning::enemy::LaneCount;
        Vector2 startPosition =
        {
            tuning::enemy::LaneStart + lane * tuning::enemy::LaneSpacing,
            -tuning::enemy::Hitbox.height * 0.5f
        };

        enemy.Spawn(
            startPosition,
            tuning::enemy::BaseSpeed,
            Enemy::Behaviour::Straight);
        ++spawnIndex;
        return;
    }
}

まずは出現位置と再利用の流れを確認します。速度の段階や波状移動の種類は、次のステップで追加します。

チェックリスト
  • 出現位置がLaneStartLaneSpacingから決まる
  • 出現間隔をEnemyManagerが管理している
  • 停止中の敵を再利用している