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

3 / 4 敵の移動処理の実装 ​

このステップの目的

直進移動とサイン波を用いた波状移動の2種類の動きをEnemy::Update()に実装します。

敵の移動ロジックとパターンの切り替え ​

敵は共通して下方向へ進みます。出現時に渡されたBehaviourの値に応じて、移動パターンを切り替えます。

敵の移動計算の流れ
経過時間
Y座標を下方向へ進める
共通移動
共通移動
Behaviourを確認
挙動分岐
挙動分岐
X座標を維持
直進
挙動分岐
baseXを中心にsinで揺らす
波状移動
移動後の敵
画面下端を越えたら停止
Deactivate

基本となる下方向への直進移動 ​

停止中の敵(!isActive)は更新処理を行いません。
有効な敵は、経過時間ageにdeltaTimeを加算し、Y座標に下方向の移動量を加えます。

Enemy.cppcpp
void Enemy::Update(float deltaTime)
{
    if (!isActive)
        return;

    // 出現からの経過時間を加算する
    age += deltaTime;

    // 下方向(+Y方向)へ一定速度で前進する
    position.y += moveSpeed * deltaTime;

画面座標系では下が+Y方向であるため、下へ進めるには加算(+=)を行います。この作品のdeltaTimeは固定の1/60秒です。速度に掛けると1回分の移動量になり、毎秒60回更新できると指定した秒速で進みます。

画面下端での消滅判定 ​

画面の最下部(tuning::ScreenHeight)を越えてプレイヤーの後方へ通り過ぎた敵は、Deactivate()を呼び出して停止状態にします。

Enemy.cppcpp
    // 画面下端より外側へ出たら停止し、プールへ戻す
    if (position.y > tuning::ScreenHeight)
        Deactivate();

停止したスロットは、次のEnemyManager::SpawnOne()の際に再び新しい敵として再利用されます。

サイン波(三角関数)による波状移動の実装 ​

behaviourがBehaviour::Waveの敵には、下方向への進行に加えて左右への周期的な揺れ(振動)を追加します。
周期的な往復運動には、三角関数のsin(サイン)が最適です。

Enemy.cppcpp
    // 波状移動の挙動であれば、sin関数を用いてX座標を左右に振動させる
    if (behaviour == Behaviour::Wave)
    {
        float waveOffset = std::sin(age * tuning::enemy::WaveSpeed)
            * tuning::enemy::WaveAmplitude;
        position.x = baseX + waveOffset;
    }

サイン波計算の仕組み ​

sin関数は、入力する角度・位相に応じて-1.0から+1.0までの値を滑らかに往復します。

  1. 角度の進む速さ: age * tuning::enemy::WaveSpeed
    std::sinの角度はラジアンです。WaveSpeedは1秒あたりに進む角度を表し、角度が約6.28(2π)進むと1往復します。値を2倍にすると、同じ時間に2倍の回数往復します。
  2. 揺れ幅(振幅): * tuning::enemy::WaveAmplitude
    -1.0 〜 +1.0の値に振幅(ピクセル幅)を掛けることで、左右に揺れる距離(例えば左右に30ピクセルずつ)を決定します。
  3. 中心軸: baseX + waveOffset
    出現時の基準X座標baseXを中心として振動を加えることで、敵全体の隊列やレーン配置を保ったまま揺らすことができます。

三角関数を使うと、複雑な物理シミュレーションを組まずに、数行のコードで滑らかで自然な動きを表現できます。

チェックリスト
  • 敵のY座標が下方向(+Y方向)へ滑らかに前進することを確認できる
  • 直進する敵が基準レーンを崩さずにまっすぐ下降することを確認できる
  • 波状移動の敵がstd::sin()によって左右に滑らかに揺れながら下降することを確認できる
  • 画面下端を越えた敵がDeactivate()され、正常にプールへ戻ることを確認できる