# 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.

Source: https://www.playdrop.ai/create/learn/lifecycle

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.

```html
<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:

```js
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.

```js
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](https://www.playdrop.ai/create/learn/catalogue-json):

```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](https://www.playdrop.ai/create/learn/instant-games) 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.

## Related guides

- [Full screen and safe areas](https://www.playdrop.ai/create/learn/viewport): Make a PlayDrop game fill the screen, keep its HUD inside CSS safe areas and clear of the host's controls using the SDK's measured reservedCorners.
- [Cloud saves](https://www.playdrop.ai/create/learn/cloud-saves): Save and load player progress with sdk.me.appData and updateAppData, for guests and signed-in players, with the rules for writes, previews and offline play.
- [Instant games](https://www.playdrop.ai/create/learn/instant-games): What makes a PlayDrop game Instant: portrait play, guest access, at most 10 MiB of startup files and a two-second start, and how it differs from regular games.
- [Client SDK](https://www.playdrop.ai/create/learn/sdk): Reference for the PlayDrop browser SDK: host lifecycle, identity and saves, controllers, social, multiplayer, shop, ads, leaderboards, assets and AI.
