Skip to content

シーンと状態管理

ゲームが大きくなると、タイトル画面・ゲーム画面・リザルト画面のように複数の「場面」を切り替える必要が出てきます。エンジンのシーン機能を使うと、各画面のセットアップを登録しておき、フェード付きで切り替えられます。

シーンの基本

シーンを登録する

engine.defineScene() でシーン名とセットアップ関数を登録します。

typescript
engine.defineScene('title', () => {
  engine.addMany([
    {
      id: 'bg',
      type: 'rect',
      x: 0,
      y: 0,
      width: engine.width,
      height: engine.height,
      fill: '#1a1a2e',
    },
    {
      id: 'title',
      type: 'text',
      x: engine.width / 2,
      y: 200,
      text: 'My Game',
      font: 'bold 32px sans-serif',
      fill: '#fff',
      align: 'center',
    },
    {
      id: 'start',
      type: 'text',
      x: engine.width / 2,
      y: 400,
      text: 'Tap to Start',
      font: '18px sans-serif',
      fill: '#aaa',
      align: 'center',
      onClick: () => engine.goTo('game'),
    },
  ]);
});

engine.defineScene('game', () => {
  // ゲームのセットアップ
  engine.addMany([/* ... */]);
  engine.onUpdate((dt) => {
    // ゲームループ
  });
});

engine.defineScene('result', () => {
  const data = engine.sceneData; // goTo で渡されたデータ
  engine.addMany([
    {
      id: 'score',
      type: 'text',
      x: engine.width / 2,
      y: 200,
      text: `Score: ${data?.score ?? 0}`,
      font: 'bold 28px sans-serif',
      fill: '#fff',
      align: 'center',
    },
  ]);
});

シーンを切り替える

engine.goTo() でシーンを切り替えます。前のシーンのノードやコールバックは自動でクリアされます。

typescript
// デフォルトのフェード遷移(300ms)
engine.goTo('game');

// 即時遷移(フェードなし)
engine.goTo('menu', { type: 'none' });

// カスタムフェード
engine.goTo('battle', { type: 'fade', duration: 500 });

シーン間でデータを渡す

goTo() の第 3 引数でデータを渡せます。遷移先のシーンでは engine.sceneData で取得します。

typescript
// データを渡す
engine.goTo('result', { type: 'fade' }, { score: 1500, rank: 'S' });

// 遷移先で受け取る
engine.defineScene('result', () => {
  const data = engine.sceneData; // { score: 1500, rank: 'S' }
  const score = data?.score ?? 0;
});

現在のシーンを確認する

typescript
engine.currentScene; // 'game' などのシーン名。シーン未使用時は null

シーン遷移時の動作

goTo() を呼ぶと、以下の処理が順番に実行されます。

  1. フェードアウト(指定されていれば)
  2. engine.clear() — 全ノード・コールバック・タイマーをクリア
  3. 遷移先のセットアップ関数を実行
  4. フェードイン

INFO

clear() はノードだけでなく onUpdate のコールバックやタイマー(setTimeout / setInterval)もクリアします。シーンごとに独立した状態を保てるため、シーン間でのリソースリークを気にする必要はありません。


グローバル状態

シーン遷移で clear() が呼ばれてもクリアされない Key-Value ストアです。ゲーム全体で共有したい値の保持に使います。

値の保存と取得

typescript
// 保存
engine.setGlobal('talkedToElder', true);
engine.setGlobal('inventory', ['sword', 'shield']);

// 取得(存在しない場合はデフォルト値を返す)
const talked = engine.getGlobal<boolean>('talkedToElder', false);
const items = engine.getGlobal<string[]>('inventory', []);

グローバル状態の用途

用途
フラグ管理NPC に話しかけたかどうか
インベントリアイテムのリスト
累積スコアステージをまたぐ合計得点
設定値難易度やボリューム

TIP

グローバル状態は engine.destroy() を呼ぶまで保持されます。ゲーム全体の進行に関わる情報だけを入れ、シーン内で完結する一時データはシーンのローカル変数を使いましょう。