React 側では engine/hooks/useGameLoop.ts と engine/stores/useGameStore.ts がゲームエンジンを UI に接続します。
useGameLoop フック#
useGameLoop((dt) => {
game.update(dt);
}, isRunning && game.isRunning);requestAnimationFrameのtimeからdt(秒)を算出。isRunningがfalseのときは RAF を解除し、lastTimeRefをリセット。- ループ中に最新のコールバック参照を使うため
useRefで callback を保持。
必要に応じて UI 側から任意の Game インスタンスを渡せます。Expo DevTools のホットリロードでも問題なく再初期化されるよう、useEffect のクリーンアップで cancelAnimationFrame を確実に呼んでいます。
Zustand ストア#
engine/stores/useGameStore.ts は Game を 1 つだけ生成し、UI からは start/pause/resume/stop をディスパッチできるようにしています。
setRenderPayload(payload)がGame.onRenderから届いたデータをtick/elapsed/entitiesに反映。toggleRunning()で UI トグルスイッチと同期。- ストアはクライアントサイドのみで使うため、サーバーレンダリングの心配は不要。
GameCanvas 以外の画面(HUD、デバッグパネル、外部ツール)でも同じストアを購読すれば、最新の World スナップショットを共有できます。