ソースコード解説・目次

CHAPTER 16 · 全23項目

編隊から突入する敵

敵に一時的な飛行状態を追加し、急降下・ジグザグ・横方向の突入を切り替えます。

主な参照先:launchFlight / updateFlights / alienRectInto / flightT / DIVER_SHOT_WAVE

同じ敵に飛行データを付け足す

game.html · L1214–1218ソースを見る ↗
function launchFlight(a, mode) {
  const r = alienRect(a);
  a.flight = { x: r.x, y: r.y, startX: r.x, t: 0, warning: 0.65, mode, phase: "exit",
    vx: clamp((player.x - r.x) * 0.5, -90, 90), side: r.x < W / 2 ? -1 : 1 };
}

突入用の別の敵を作るのではなく、元の敵へ flight を付けます。編隊の行と列は残したまま、現在座標、経過時間、0.65秒の予告、飛び方、左右の向きなどを保存します。予告中も編隊の共通移動から外れます。

3種類の軌道

モード位置の更新
dive下へ進みながら、開始時に決めた横速度を加える
zigzagMath.sin(f.t * 5) * 54 で左右に揺れながら降下
flank一度横へ退場し、自機の少し上の高さから横切る

突入はウェーブ2以降で、ボス戦と開始バナー中には発生しません。候補は生きていてまだ飛行していない敵です。同時に飛べる数と発生間隔はウェーブに応じて変化します。モードは3種類を順番に使います。

game.html · L1235–1256ソースを見る ↗
    const speed = Math.min(260, 155 + wave * 7);
    if (f.mode === "flank" && f.phase === "exit") {
      f.x += f.side * speed * dt;
      if (f.x < -30 || f.x > W + 30) {
        f.phase = "attack"; f.y = PLAYER_Y - 160;
        f.x = f.side < 0 ? -28 : W + 4;
      }
    } else {
      f.y += speed * dt;
      if (f.mode === "zigzag") f.x = clamp(f.startX + Math.sin(f.t * 5) * 54, 5, W - 29);
      else f.x += (f.mode === "flank" ? -f.side * speed * 1.5 : f.vx) * dt;
      // ウェーブ 11 からは、降下の途中で(自機から 200px 以上離れているうちに)自機を狙って 1 発撃つ。
      if (wave >= DIVER_SHOT_WAVE && !f.shot && f.y > PLAYER_Y - 320 && f.y < PLAYER_Y - 200 &&
          f.x > 0 && f.x < W - 24 && eBullets.length < maxEnemyBullets()) {
        const t = TYPES[a.type];
        f.shot = true;
        enemyShot(f.x + t.w / 2 - 1.5, f.y + t.h, true);
      }
      if (player.alive && player.inv <= 0 && hit(alienRect(a), playerRect())) damagePlayer();
      if (f.y > GROUND_Y + 24 || f.x < -60 || f.x > W + 60) a.flight = null;
    }
    if (state !== "play") return;

ウェーブ11 (DIVER_SHOT_WAVE) からは、降下の途中で自機を狙って1発撃ちます。撃つのは自機から200〜320 px上にいる間だけなので、弾が届くまでに避ける時間があります。f.shot に撃ったことを記録して、1回の突入で1発に限ります。画面の外にいる間と、画面内の敵弾が上限に達しているときは撃たず、範囲内にいる間に上限が空けば撃ちます。弾は編隊の狙い撃ちと同じ enemyShot() で作ります(「07 敵の編隊とウェーブ生成」)。

画面外へ出たら編隊へ戻す

飛行範囲から出た敵は a.flight = null に戻します。次の当たり判定・描画では、元の行と列に現在の編隊原点を足した位置を使います。敵は生存したままなので、撃破するまでウェーブが続きます。