# PlayDrop のゲームライフサイクル：読み込み、準備完了、一時停止、オーディオ

PlayDrop SDK を初期化し、最初の遊べるフレームで準備完了を伝え、きれいに一時停止・再開し、ホストのオーディオポリシーに従い、アプリとオフライン用にファイルを事前読み込みします。

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

PlayDrop は、ゲームのまわりに独自の読み込み画面、一時停止メニュー、ミュートボタンなどのウィンドウを表示します。ライフサイクル API は、ゲームをそれらと連動させます。PlayDrop が一時停止している間はゲームを止め、PlayDrop のオーディオポリシーが許可しているときだけ音を鳴らします。

## 初期化してから準備完了を伝える

SDK を読み込み、初期状態を読み取り、変更を購読し、最初の画面を準備してから、はじめて `ready()` を呼び出します。それまで PlayDrop は読み込み画面を表示し続けます。

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

`ready()` は、アセットの読み込み前ではなく、意図した最初の画面が表示されて操作が効くようになってから呼び出してください。`sdk.host.error(message)` は、ゲームを開始できないことを PlayDrop に伝えます。`setLoadingState` と `firstFrameReady` は同じ処理の古い名前です。`ready()` を使ってください。

## フェーズ：プレビュー、プレイ、エディター

`sdk.host.phase` は `preview`、`play`、`editor` のいずれかで、切り替わると `onPhaseChange` で通知されます。プレビューとキャプチャは、実際のセッションなしでゲームを表示します。`play` 以外では、セーブ、スコア、実績、購入を絶対に書き込まないでください。`sdk.host.mode` は通常 `play` で、ローカルの Dev フレームでは `dev` です。

## 一時停止と再開

`onPause(reason)` と `onResume(reason)` は、プレイヤーが一時停止メニューを開いたとき、タブを隠したとき、サインインしたとき、何かを購入したとき、または広告や PlayDrop のウィンドウがゲームを覆ったときに呼ばれます。`reason` は `tab_hidden`、`auth_prompt`、`purchase_flow`、`host_overlay`、`detail_hidden`、`route_change`、`native_background` のいずれかで、`sdk.host.isPaused` は現在の状態です。

一時停止中は、シミュレーションとタイマーを止めます。再開時はフレームの時計をリセットして、ゲームが先へ飛ばないようにします。

```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);
```

Esc キーとコントローラーのメニューボタンは PlayDrop の一時停止メニューに使われます。ゲームで割り当てないでください。ネットワーク対応のゲームでは、一時停止中もルームの接続を維持してください。1人のプレイヤーが一時停止しても、ほかのプレイヤーを止めてはいけません。

## オーディオ

`init()` のあとに `sdk.host.audioAllowed` を1回読み取り、その後は `onAudioAllowedChange` に従います。この値はプレイヤーのミュート、フェーズ、一時停止をまとめたもので、タブが隠れたことによる一時停止中は true のままなので、音楽は再生位置を保てます。理由やホストの音量も必要な場合は、`onAudioPolicyChange` が `{ enabled, reason, volume }` を通知します。

```js
const audio = new AudioContext();
function setAudio(allowed) {
  (allowed ? audio.resume() : audio.suspend()).catch(() => {});
}
```

オーディオはホストが許可するまでミュートで始まり、さらにブラウザでは、音が鳴る前にプレイヤーの操作が必要です。ゲーム内の音量設定は、追加の上限として残してください。ホストのミュートが常に優先されます。拒否された `play()` と `resume()` の Promise は catch してください。

## アプリでの事前読み込みとオフラインプレイ

ネイティブアプリは、ゲームの開始前にファイルをダウンロードし、オフラインで遊べるよう保存しておけます。ファイルは [catalogue.json](https://www.playdrop.ai/ja/create/learn/catalogue-json) で宣言します。

```json
{
  "prefetch": { "required": ["game.js", "assets/level-1.png"], "optional": ["assets/music.mp3"] },
  "offlineSupported": true
}
```

エントリーページは常に含まれます。`required` のファイルはプレイ前に、`optional` のファイルはプレイ開始後に取得されます。`offlineSupported: true` にすると、必須ファイルの保存が済んだゲームを、アプリがオフラインで提供できるようになります。無効な値は無視され、アップロードを妨げることはありません。ウェブサイトは通常どおりゲームを読み込みます。[インスタント](https://www.playdrop.ai/ja/create/learn/instant-games)ゲームでは、必須ファイルの合計が起動ファイルのサイズになります。

デバイスデータへの対応を示すホストでは、オフラインで行ったセーブ、スコア、実績はデバイスに残り、オンラインになると同期されます。オフラインのランキングには、プレイヤー自身の自己ベストだけが表示されます。ブラウザにはオフライン用のキューがないため、セーブの失敗に対処してください。ゲームがインターネットから読み込むものには、引き続き接続が必要です。

## 振動フィードバック

ネイティブアプリでは、`sdk.haptics.selection()`、`impact("light" | "medium" | "heavy")`、`notification("success" | "warning" | "error")` で短い振動フィードバックを返せます。ホストが対応しているかどうかは `sdk.haptics.supported` でわかります。ウェブでは何も起きず、ミュートとは関係なく動作します。

## 関連ガイド

- [全画面とセーフエリア](https://www.playdrop.ai/ja/create/learn/viewport): PlayDrop ゲームを画面いっぱいに表示し、SDK が計測した reservedCorners を使って、HUD を CSS のセーフエリア内に収め、ホストのボタンと重ならないようにします。
- [クラウドセーブ](https://www.playdrop.ai/ja/create/learn/cloud-saves): sdk.me.appData と sdk.me.updateAppData でプレイヤーの進行状況を保存・読み込みます。ゲストとサインイン中のプレイヤーへの対応、書き込み、プレビュー、オフラインのルールも説明します。
- [インスタントゲーム](https://www.playdrop.ai/ja/create/learn/instant-games): PlayDrop のゲームがインスタントになる条件：縦向きのプレイ、ゲストの利用、起動ファイル 10 MiB 以内、2秒以内の起動。通常のゲームとの違いも説明します。
- [クライアント SDK](https://www.playdrop.ai/ja/create/learn/sdk): PlayDrop ブラウザ SDK のリファレンス：初期化、ホストのライフサイクル、プレイヤー情報とセーブ、デバイスとコントローラー、ソーシャル、マルチプレイヤー、ショップ、広告、ランキング、実績、アセット、AI。
