Webゲーム等で使われる構造パターン

SceneManager

🎮 SceneManagerとは?

ゲームは実は 画面の集合です。

タイトル

ゲーム選択

ミニゲーム

リザルト

称号画面

これらを Scene(シーン) と呼びます。

🧠 SceneManagerの役割

SceneManagerは

今どの画面か?

を管理します。

currentScene = TitleScene

そして毎フレーム

update()
draw()

を呼びます。

🎮 完成形のイメージ

SceneManager

TitleScene
GameSelectScene
MiniGameScene
ResultScene
CollectionScene

🧩 ① Sceneの基本クラス

まず すべての画面の共通クラスを作ります。

🧠 ② SceneManager

これがゲームの司令塔です。

🎮 ③ メインループ

🎮 ④ タイトル画面

🎮 ⑤ ゲーム選択画面

🎮 ⑥ ミニゲーム画面

🎮 ⑦ リザルト画面

🎮 ⑧ 最初のシーン

🚀 これで完成するゲーム構造

TitleScene

GameSelectScene

MiniGameScene

ResultScene

TitleScene

関連記事(jsでボタンをクラスでまとめる)

リンク

Webゲーム定番パターン

① 基本思想

JSを 役割ごとに分離します。

state   = 状態管理
ui = 画面操作
api = サーバー通信
actions = ボタン処理

構造

janken-game.js

中身

Game
├ state
├ ui
├ api
└ actions

② 全体の基本構造

const Game = {  state: {},
ui: {},
api: {},
actions: {}};

この Gameオブジェクトに全部入れるのがポイントです。

理由

グローバル汚染を防ぐ

③ state(ゲーム状態)

ここは データ保存専用

Game.state = {  playerId: null,
playerName: "",
selectedHand: null,
attackTarget: null,
round: null};

重要ルール

stateはデータだけ
DOM触らない

④ UIモジュール

画面更新は全部ここ。

Game.ui = {  show(el){
document.getElementById(el).style.display = "block";
}, hide(el){
document.getElementById(el).style.display = "none";
}, setText(id,text){
document.getElementById(id).textContent = text;
}};

例えば

Game.ui.setText("player-name", "なまえ");

⑤ APIモジュール

サーバー通信はここだけ。

Game.api = {  async register(name){    const res = await fetch("/api/register",{
method:"POST",
body:JSON.stringify({name})
}); return res.json(); }, async attack(data){ const res = await fetch("/api/attack",{
method:"POST",
body:JSON.stringify(data)
}); return res.json(); }};

メリット

API変更がここだけで済む

⑥ actions(ボタン処理)

ここが ゲームロジック

Game.actions = {  async register(){    const name =
document.getElementById("display-name").value; const res = await Game.api.register(name); Game.state.playerId = res.id; Game.ui.setText("player-name", name); Game.ui.hide("register-box");
Game.ui.show("game-box"); }};

⑦ イベント委任

クリック管理は1か所だけ。

document
.getElementById("janken-app")
.addEventListener("click",(e)=>{ const action = e.target.dataset.action; if(!action) return; if(Game.actions[action]){
Game.actions[action](e);
}});

⑧ HTMLはこう変える

<button data-action="register">登録する</button><button data-action="revive">復活する</button><button data-action="startSet">カードをセット</button><button data-action="startAttack">カードに挑む</button>

JSは触らなくてOK。

⑨ 手ボタン

<button data-hand="guu">✊</button>
<button data-hand="choki">✌️</button>
<button data-hand="paa">✋</button>

JS

if(e.target.dataset.hand){  Game.state.selectedHand =
e.target.dataset.hand;}

⑩ とあるパターンのゲームでの完成構造

JSファイル

janken-game.js

構造

Game
├ state
│ ├ player
│ ├ round
│ └ selectedHand

├ ui
│ ├ show
│ ├ hide
│ ├ updateProfile
│ └ updateRanking

├ api
│ ├ register
│ ├ revive
│ ├ setCard
│ └ attack

└ actions
├ register
├ revive
├ startSet
├ submitCard
└ attack

スクロールゲームでのオブジェクト管理パターン

代表的な手法

1. オブジェクトプール(Object Pool)パターン

最もよく使われる手法です。

メリット: push/filter による配列の生成・GC負荷ゼロ。60fps維持に有利。

2. チャンクベースのスポーン

横スクロールゲームで多用されます。

  • プレイヤーが進んだ分だけ「前方一定距離」にオブジェクトを生成
  • 「最後のオブジェクトからの距離」ではなく「cameraX + 画面幅 + マージン」を閾値にする

3. イベント駆動スポーン

シンプルですが、生成条件と削除条件が独立していることが重要です。

コメント

タイトルとURLをコピーしました