テーマ
シーンと状態管理
ゲームが大きくなると、タイトル画面・ゲーム画面・リザルト画面のように複数の「場面」を切り替える必要が出てきます。エンジンのシーン機能を使うと、各画面のセットアップを登録しておき、フェード付きで切り替えられます。
シーンの基本
シーンを登録する
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() を呼ぶと、以下の処理が順番に実行されます。
- フェードアウト(指定されていれば)
engine.clear()— 全ノード・コールバック・タイマーをクリア- 遷移先のセットアップ関数を実行
- フェードイン
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() を呼ぶまで保持されます。ゲーム全体の進行に関わる情報だけを入れ、シーン内で完結する一時データはシーンのローカル変数を使いましょう。