# วงจรชีวิตของเกมบน PlayDrop: การโหลด ready การหยุดชั่วคราว และเสียง

เริ่มต้น PlayDrop SDK ส่งสัญญาณ ready ที่เฟรมแรกที่เล่นได้ หยุดชั่วคราวและเล่นต่ออย่างเรียบร้อย ทำตามนโยบายเสียง และโหลดไฟล์ล่วงหน้าเพื่อเล่นออฟไลน์

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

PlayDrop แสดงหน้าจอโหลด เมนูหยุดชั่วคราว ปุ่มปิดเสียง และหน้าต่างอื่นๆ ของตัวเองรอบเกมของคุณ API วงจรชีวิตทำให้เกมทำงานสอดคล้องกับสิ่งเหล่านี้: เกมจะหยุดเมื่อ PlayDrop หยุดเกมชั่วคราว และเล่นเสียงเฉพาะเมื่อนโยบายเสียงของ PlayDrop อนุญาต

## เริ่มต้น แล้วส่งสัญญาณ ready

โหลด 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);
```

ปุ่ม Escape และปุ่ม Menu ของคอนโทรลเลอร์เป็นของเมนูหยุดชั่วคราวของ PlayDrop อย่าผูกปุ่มเหล่านี้ในเกมของคุณ ในเกมที่เล่นผ่านเครือข่าย ให้คงการเชื่อมต่อห้องไว้ขณะหยุดชั่วคราว: การหยุดของผู้เล่นคนหนึ่งต้องไม่ทำให้คนอื่นหยุดไปด้วย

## เสียง

อ่าน `sdk.host.audioAllowed` หนึ่งครั้งหลัง `init()` แล้วทำตาม `onAudioAllowedChange` ค่านี้รวมการปิดเสียงของผู้เล่น ช่วงของเกม และการหยุดชั่วคราวเข้าด้วยกัน และยังคงเป็น true ระหว่างการหยุดเพราะซ่อนแท็บ เพื่อให้เพลงคงตำแหน่งที่เล่นอยู่ได้ `onAudioPolicyChange` รายงาน `{ enabled, reason, volume }` เมื่อคุณต้องการรู้เหตุผลหรือระดับเสียงของโฮสต์ด้วย

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

เสียงเริ่มแบบปิดไว้จนกว่าโฮสต์จะอนุญาต และเบราว์เซอร์ยังต้องการการกระทำจากผู้เล่นก่อนจึงจะเล่นเสียงได้ หากเกมมีการตั้งค่าระดับเสียงของตัวเอง ให้ใช้เป็นข้อจำกัดเพิ่มเติม การปิดเสียงของโฮสต์มีผลเหนือกว่าเสมอ ดักจับ promise ของ `play()` และ `resume()` ที่ถูกปฏิเสธ

## โหลดล่วงหน้าและเล่นออฟไลน์ในแอป

แอปเนทีฟดาวน์โหลดไฟล์ของเกมได้ก่อนเกมเริ่ม และเก็บไว้เพื่อเล่นออฟไลน์ ประกาศไฟล์เหล่านี้ใน [catalogue.json](https://www.playdrop.ai/th/create/learn/catalogue-json):

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

หน้าเริ่มต้นถูกรวมไว้เสมอ ไฟล์ `required` จะดาวน์โหลดก่อนเล่น ส่วนไฟล์ `optional` ดาวน์โหลดหลังจากนั้น `offlineSupported: true` ให้แอปเสนอเกมแบบออฟไลน์ได้เมื่อเก็บไฟล์ที่จำเป็นไว้แล้ว ค่าที่ไม่ถูกต้องจะถูกละเว้นและไม่ขัดขวางการอัปโหลด เว็บไซต์โหลดเกมตามปกติ สำหรับเกม [Instant](https://www.playdrop.ai/th/create/learn/instant-games) ไฟล์ที่จำเป็นเหล่านี้คือสิ่งที่นับเป็นขนาดไฟล์เริ่มต้น

บนโฮสต์ที่ประกาศว่ารองรับข้อมูลบนอุปกรณ์ ข้อมูลบันทึก คะแนน และความสำเร็จที่เกิดขึ้นขณะออฟไลน์จะอยู่บนอุปกรณ์และซิงค์เมื่อออนไลน์ ลีดเดอร์บอร์ดแบบออฟไลน์จะแสดงเฉพาะสถิติที่ดีที่สุดของผู้เล่นเอง ในเบราว์เซอร์ไม่มีคิวออฟไลน์ จึงต้องจัดการเมื่อบันทึกล้มเหลว ทุกอย่างที่เกมโหลดจากอินเทอร์เน็ตยังต้องใช้การเชื่อมต่อ

## การสั่น

ในแอปเนทีฟ `sdk.haptics.selection()`, `impact("light" | "medium" | "heavy")` และ `notification("success" | "warning" | "error")` ให้การตอบสนองแบบสั่นสั้นๆ ส่วน `sdk.haptics.supported` บอกว่าโฮสต์ทำได้หรือไม่ ฟังก์ชันเหล่านี้ไม่ทำอะไรบนเว็บ และไม่ขึ้นกับการปิดเสียง

## คู่มือที่เกี่ยวข้อง

- [เต็มหน้าจอและพื้นที่ปลอดภัย](https://www.playdrop.ai/th/create/learn/viewport): ทำให้เกม PlayDrop เต็มหน้าจอ เก็บ HUD ไว้ในพื้นที่ปลอดภัยของ CSS และไม่ทับปุ่มควบคุมของโฮสต์ด้วย reservedCorners ที่ SDK วัดให้
- [การบันทึกบนคลาวด์](https://www.playdrop.ai/th/create/learn/cloud-saves): บันทึกและโหลดความคืบหน้าของผู้เล่นด้วย sdk.me.appData และ updateAppData สำหรับผู้เยี่ยมชมและผู้เล่นที่เข้าสู่ระบบ พร้อมกฎการเขียน การแสดงตัวอย่าง และการเล่นออฟไลน์
- [เกม Instant](https://www.playdrop.ai/th/create/learn/instant-games): อะไรทำให้เกม PlayDrop เป็นเกม Instant: เล่นแนวตั้ง ผู้เยี่ยมชมเล่นได้ ไฟล์เริ่มต้นไม่เกิน 10 MiB และเริ่มได้ในสองวินาที และต่างจากเกมทั่วไปอย่างไร
- [SDK ฝั่งไคลเอนต์](https://www.playdrop.ai/th/create/learn/sdk): เอกสารอ้างอิง SDK บนเบราว์เซอร์ของ PlayDrop: วงจรชีวิตของโฮสต์ ตัวตนและการบันทึก คอนโทรลเลอร์ โซเชียล ผู้เล่นหลายคน ร้านค้า โฆษณา ลีดเดอร์บอร์ด แอสเซ็ต และ AI
