Implement lifecycle and pause handling
Initialise correctly and distinguish game breaks from host pauses.
Required order
import llvls from '@llvls/sdk';
const context = await llvls.init();
// Prepare the game and load its assets here.
llvls.loadingProgress(1);
await llvls.ready();
llvls.gameplayStart();
// Call gameplayStop() at a natural break.
// Call gameOver() when the entire run ends.
ready() shows the tap-to-play gate and resolves after the player activates it. Start audio after it resolves. Call it within 30 seconds of the frame loading, or the load counts as failed. This deadline is for calling ready(), not for the player to tap.
Subscribe to host events
Install handlers before initialisation can deliver events. On pause, freeze simulation, ignore gameplay input and silence audio. On resume, continue only the state that should still be active. Do not turn a completed run back into an active run simply because an overlay closed.
Keep host-paused, game-at-menu and user-muted state separate. An overlay closing must not unmute the player’s audio preference. Use the initial context’s muted and reducedMotion values.
For an animation loop, cancel scheduled frames on pause or guard updates, clear held keys and reset your previous timestamp on resume to avoid a large time step.
Finish a run
Call gameOver() once when the run ends. It also marks a break. The host may show its own next-game panel, but previews and unlisted games do not necessarily show one. A host Play again action reloads the frame; the game does not receive the player’s choice.
Do not infer a counted play or an ad impression from lifecycle calls. The host counts activity independently.