Start a game
Goal
Share one Play action between people, the sandbox and playtest.
Files you will edit
src/main.ts— the page's Play action and existing button.src/game.ts— gameplay latches in the guest.
Steps
In page code, register everything the existing Play action does with
onStart; never start through another DOM event or guessed key.tsimport { onStart, startGame } from 'gameable/host'; onStart(({ reason }) => { document.querySelector('#title')?.classList.add('hidden'); if (reason === 'player') { document.querySelector('canvas')?.requestPointerLock(); } }); document.querySelector('#play')?.addEventListener('click', () => { void startGame({ reason: 'player' }); });Callbacks run once in order; the first runs synchronously. Promises are awaited. Capture skips pointer lock and audio permission. Unregister on disposal.
Gate gameplay with
ctx.started: true before systems receive thestartevent, until init. Keep drawing camera/HUD while waiting. First-input latches must also acceptstart(reasons:player,capture,playtest).tsimport { defineGame } from 'gameable'; export default defineGame({ update(ctx) { if (!ctx.started) return; }, });
Solo ctx.data saves persist; version them with defineGame({ save: { version, migrate } }).
Verify
Press Play. Reload; the sandbox calls await window.__gameable.startGame({ reason: 'capture' }); the playtest agent uses { reason: 'playtest' }. Omitting options defaults to player. Both paths run Play and send one guest event. The promise waits for two rendered frames after enqueue. Repeated calls resolve immediately, even during Play. window.__gameable.started is read-only: true when the event is queued. Callback failures reject once; later calls do not retry. Rebuild compiled guests.
See also
Use defineGame({ framework: 'default' }) for default match actors and HUD; ctx.pause.push('menu') pauses until the page calls game.pause.pop('menu'). Travel removes level actors and code spawns; mark actors persist: 'session' to keep them with players, and use ctx.levels.load(ctx, name, { arrival: true }) to require a destination start before teardown.