10.【JS】SVGシューティングをFSMで整理する|DOMゲームを壊さないための中間設計

tags: [“JavaScript”, “SVG”, “FSM”, “GameDev”]


🎮 SVGシューティングを FSM で整理する

— DOMゲームを「動く」から「壊さずに育てる」へ —

⚠️ この記事は「完成版」ではありません。

最初に位置づけをはっきりさせます。

👉
ゲームを遊びたい人は 12_ へ直行してください。
この記事は「作る側のための整理メモ」です。


09_ では何をやったか

09_ では、Canvas を使わずに

だけでシューティングゲームを成立させました。

👉 ちゃんと動くことは確認できた


でも、作っていると違和感が出る

機能を足し始めると、コードにこういうものが増えてきます。


⚠️ 09_ の限界

👉 原因ははっきりしています。

ゲームの「状態」が
コード上で明示されていない


🧠 解決策:FSM(有限状態機械)

この記事でやることはシンプルです。

ゲームが今どの状態かを
1つの変数で表す

難しい理論は使いません。


🧩 状態定義

const State = {
  INIT: "init",         // 初期化
  READY: "ready",       // 開始待ち
  PLAY: "play",         // プレイ中
  GAME_OVER: "game_over"
};

let currentState = State.INIT;

👉 「今どの状態か」を必ずここで管理します。


🔄 状態遷移は1か所に集める

function changeState(next) {
  console.log(`STATE: ${currentState}${next}`);
  currentState = next;
}

👉 ログを見るだけでゲームの流れが分かります。


🎮 メインループを FSM 前提で整理する

09_ では if が散らばっていましたが、
FSM を入れるとこう書けます。

function gameLoop() {
  switch (currentState) {

    case State.INIT:
      initGame();
      changeState(State.READY);
      break;

    case State.READY:
      // スタート入力待ち
      break;

    case State.PLAY:
      updatePlayer();
      updateEnemies();
      updateBullets();
      checkCollision();
      break;

    case State.GAME_OVER:
      // リスタート待ち
      break;
  }

  requestAnimationFrame(gameLoop);
}

✨ 今「何をしているゲームか」が一目で分かる
✨ if 地獄から抜け出せる


⌨️ 入力処理も状態で意味を変える

document.addEventListener("keydown", e => {

  if (currentState === State.READY && e.code === "Space") {
    changeState(State.PLAY);   // 開始
  }

  if (currentState === State.GAME_OVER && e.code === "KeyR") {
    changeState(State.INIT);   // 再スタート
  }
});

👉 入力は「状態遷移のきっかけ」になる
👉 無駄なフラグ管理が消える


🧠 SVG(DOM) と FSM は相性がいい

👉 Canvas より 設計を説明しやすい
👉 教材向き


📐 全体構造(この段階)

Game FSM
 ├─ INIT
 ├─ READY
 ├─ PLAY
 └─ GAME_OVER
      │
      └─ SVG(DOM)
           ├─ player
           ├─ bullets
           └─ enemies

✨ この段階で得られるもの

でも、


🔮 次(11_)でやること


🎯 まとめ(正直版)

FSMは目的ではありません。
ゲームを壊さずに作り続けるための道具です。