Game lifecycle on PlayDrop: loading, ready, pause and audio
Initialize the PlayDrop SDK, signal ready at the first playable frame, pause and resume cleanly, follow the audio policy, and preload files for offline play.
PlayDrop shows its own loading screen, pause menu, mute control and other windows around your game. The lifecycle API keeps the game in step with them: it stops while PlayDrop pauses it and plays sound only when PlayDrop's audio policy allows.
Initialize, then signal ready
Load the SDK, read the initial state, subscribe to changes, prepare the first screen and only then call ready(). PlayDrop keeps its loading screen up until then.
<script src="https://assets.playdrop.ai/sdk/playdrop.js"></script>
<script type="module">
const sdk = await playdrop.init();
let paused = sdk.host.isPaused;
setAudio(sdk.host.audioAllowed);
sdk.host.onAudioAllowedChange(setAudio);
sdk.host.onPause(() => { paused = true; });
sdk.host.onResume(() => { paused = false; last = performance.now(); });
try {
await loadFirstLevel();
} catch (error) {
sdk.host.error("Could not load the first level");
throw error;
}
drawFirstFrame();
sdk.host.ready();
</script>Call ready() once the designed first screen is visible and input works, not before assets load. sdk.host.error(message) tells PlayDrop the game cannot start. setLoadingState and firstFrameReady are older names for the same step; use ready().
Phases: preview, play and editor
sdk.host.phase is preview, play or editor, and onPhaseChange reports switches. Previews and captures show the game without a real session: never write saves, scores, achievements or purchases outside play. sdk.host.mode is play normally and dev in the local Dev frame.
Pause and resume
onPause(reason) and onResume(reason) fire when the player opens the pause menu, hides the tab, signs in, buys something, or when an ad or a PlayDrop window covers the game. reason is one of tab_hidden, auth_prompt, purchase_flow, host_overlay, detail_hidden, route_change or native_background; sdk.host.isPaused is the current state.
While paused, stop simulation and timers. On resume, reset your frame clock so the game does not jump forward:
let last = performance.now();
function frame(now) {
const dt = paused ? 0 : Math.min((now - last) / 1000, 0.05);
last = now;
if (!paused) update(dt);
render();
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);Escape and a controller's Menu button belong to PlayDrop's pause menu; do not bind them in your game. In a networked game, keep the room connection alive while paused: pausing one player must not stop the others.
Audio
Read sdk.host.audioAllowed once after init(), then follow onAudioAllowedChange. It combines the player's mute, the phase and pause, and stays true during a hidden-tab pause so music can keep its position. onAudioPolicyChange reports { enabled, reason, volume } when you also need the reason or the host volume.
const audio = new AudioContext();
function setAudio(allowed) {
(allowed ? audio.resume() : audio.suspend()).catch(() => {});
}Audio starts muted until the host allows it, and browsers still need a player gesture before sound plays. Keep any in-game volume setting as a further limit; the host mute always wins. Catch rejected play() and resume() promises.
Preload and play offline in the apps
The native apps can download a game's files before it starts and keep them for offline play. Declare them in catalogue.json:
{
"prefetch": { "required": ["game.js", "assets/level-1.png"], "optional": ["assets/music.mp3"] },
"offlineSupported": true
}The entry page is always included. required files are fetched before play; optional ones after. offlineSupported: true lets the apps offer the game offline once its required files are stored. Invalid values are ignored and never block an upload. The website loads games as usual. For Instant games, the required files are the startup size.
On hosts that advertise device-data support, saves, scores and achievements made offline stay on the device and sync once online; offline leaderboards show only the player's own best. In a browser there is no offline queue, so handle a failed save. Anything the game loads from the internet still needs a connection.
Haptics
In the native apps sdk.haptics.selection(), impact("light" | "medium" | "heavy") and notification("success" | "warning" | "error") give short feedback; sdk.haptics.supported says whether the host can. They do nothing on the web and are independent of mute.