You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/th/6-space-game/6-end-condition/README.md

675 lines
54 KiB

# สร้างเกมอวกาศ ตอนที่ 6: สิ้นสุดและเริ่มใหม่
```mermaid
journey
title การเดินทางสู่การจบเกมของคุณ
section เงื่อนไขการสิ้นสุด
กำหนดสถานะชนะ/แพ้: 3: Student
ดำเนินการตรวจสอบเงื่อนไข: 4: Student
จัดการการเปลี่ยนสถานะ: 4: Student
section ประสบการณ์ผู้เล่น
ออกแบบระบบตอบกลับ: 4: Student
สร้างกลไกการเริ่มต้นใหม่: 5: Student
ขัดเงาอินเทอร์เฟซผู้ใช้: 5: Student
section การรวมระบบ
จัดการวงจรชีวิตเกม: 5: Student
จัดการล้างหน่วยความจำ: 5: Student
สร้างประสบการณ์ที่สมบูรณ์: 5: Student
```
เกมที่ยอดเยี่ยมทุกเกมต้องมีเงื่อนไขการจบที่ชัดเจนและกลไกเริ่มใหม่ที่ราบรื่น คุณได้สร้างเกมอวกาศที่น่าประทับใจที่มีการเคลื่อนที่ การต่อสู้ และการให้คะแนนแล้ว - ตอนนี้ถึงเวลาที่จะเพิ่มส่วนสุดท้ายที่ทำให้เกมรู้สึกสมบูรณ์
เกมของคุณตอนนี้ทำงานได้ไม่สิ้นสุด เหมือนกับยานสำรวจ Voyager ที่ NASA ส่งขึ้นไปในปี 1977 - ยังเดินทางในอวกาศอยู่หลายสิบปีหลังจากนั้น แม้ว่าจะดีสำหรับการสำรวจอวกาศ แต่เกมต้องมีจุดสิ้นสุดที่กำหนดเพื่อสร้างประสบการณ์ที่น่าพึงพอใจ
วันนี้เราจะนำเงื่อนไขชนะ/แพ้ที่เหมาะสมและระบบเริ่มต้นใหม่มาใช้ เมื่อจบบทเรียนนี้ คุณจะมีเกมที่ขัดเกลาแล้วที่ผู้เล่นสามารถจบและเล่นซ้ำได้ เหมือนกับเกมอาร์เคดคลาสสิกที่เป็นตัวแทนของวงการนี้
```mermaid
mindmap
root((การจบเกม))
End Conditions
Victory States [สถานะชัยชนะ]
Defeat Conditions [เงื่อนไขความพ่ายแพ้]
Progress Tracking [การติดตามความคืบหน้า]
State Validation [การตรวจสอบสถานะ]
Player Feedback
Visual Messages [ข้อความภาพ]
Color Psychology [จิตวิทยาสี]
Clear Communication [การสื่อสารที่ชัดเจน]
Emotional Response [การตอบสนองทางอารมณ์]
State Management
Game Loop Control [การควบคุมลูปเกม]
Memory Cleanup [การล้างหน่วยความจำ]
Object Lifecycle [วงจรชีวิตของวัตถุ]
Event Handling [การจัดการเหตุการณ์]
Restart Systems
Input Handling [การจัดการอินพุต]
State Reset [การรีเซ็ตสถานะ]
Fresh Initialization [การเริ่มต้นใหม่]
User Experience [ประสบการณ์ผู้ใช้]
Polish Elements
Message Display [การแสดงข้อความ]
Smooth Transitions [การเปลี่ยนผ่านที่ราบรื่น]
Error Prevention [การป้องกันข้อผิดพลาด]
Accessibility [การเข้าถึง]
```
## แบบทดสอบก่อนเรียน
[แบบทดสอบก่อนเรียน](https://ff-quizzes.netlify.app/web/quiz/39)
## ความเข้าใจเกี่ยวกับเงื่อนไขการจบเกม
เกมของคุณควรจบเมื่อใด? คำถามพื้นฐานนี้ได้กำหนดการออกแบบเกมตั้งแต่ยุคแรกของอาร์เคด Pac-Man จบเมื่อคุณถูกผีจับหรือเก็บจุดทั้งหมด ในขณะที่ Space Invaders จบเมื่อมนุษย์ต่างดาวบุกถึงด้านล่างหรือถูกทำลายหมดแล้ว
ในฐานะผู้สร้างเกม คุณเป็นผู้กำหนดเงื่อนไขชนะและแพ้ สำหรับเกมอวกาศของเรา นี่คือวิธีที่พิสูจน์แล้วว่าสร้างการเล่นเกมที่น่าดึงดูดใจ:
```mermaid
flowchart TD
A["🎮 เริ่มเกม"] --> B{"ตรวจสอบเงื่อนไข"}
B --> C["จำนวนศัตรู"]
B --> D["ชีวิตของฮีโร่"]
B --> E["คะแนนเป้าหมาย"]
B --> F["ความก้าวหน้าในระดับ"]
C --> C1{"ศัตรู = 0?"}
D --> D1{"ชีวิต = 0?"}
E --> E1{"คะแนน ≥ เป้าหมาย?"}
F --> F1{"ทำภารกิจเสร็จสมบูรณ์?"}
C1 -->|ใช่| G["🏆 ชัยชนะ"]
D1 -->|ใช่| H["💀 แพ้"]
E1 -->|ใช่| G
F1 -->|ใช่| G
C1 -->|ไม่| B
D1 -->|ไม่| B
E1 -->|ไม่| B
F1 -->|ไม่| B
G --> I["🔄 ตัวเลือกเริ่มใหม่"]
H --> I
style G fill:#e8f5e8
style H fill:#ffebee
style I fill:#e3f2fd
```
- **ทำลายยานศัตรู `N` ลำ**: เป็นเรื่องปกติถ้าคุณแบ่งเกมออกเป็นเลเวลต่างๆ ที่ต้องทำลายยานศัตรูจำนวน `N` เพื่อผ่านเลเวล
- **ยานของคุณถูกทำลาย**: มีเกมหลายเกมที่คุณจะแพ้ถ้ายานตัวเองถูกทำลาย อีกวิธีหนึ่งที่ใช้คือมีแนวคิดของชีวิต ทุกครั้งที่ยานถูกทำลายจะเสียชีวิตหนึ่งครั้ง เมื่อเสียชีวิตหมดแล้วจึงแพ้
- **คุณเก็บคะแนนได้ `N` คะแนน**: อีกเงื่อนไขการจบที่พบบ่อยคือการเก็บคะแนน วิธีที่คุณได้คะแนนขึ้นอยู่กับคุณ แต่มักจะให้คะแนนจากกิจกรรมต่างๆ เช่น ทำลายยานศัตรูหรือเก็บไอเท็มที่หล่นจากการทำลาย
- **ผ่านเลเวล**: อาจจะรวมหลายเงื่อนไข เช่น ทำลายยานศัตรู `X` ลำ, เก็บคะแนนได้ `Y` คะแนน หรือเก็บไอเท็มเฉพาะได้
## การใช้งานฟังก์ชันเริ่มเกมใหม่
เกมที่ดีสร้างความน่าสนใจให้ผู้เล่นเล่นซ้ำด้วยระบบเริ่มใหม่ที่ราบรื่น เมื่อผู้เล่นจบเกม (หรือแพ้) พวกเขามักอยากเล่นใหม่ทันที ไม่ว่าจะเพื่อทำคะแนนให้ดีกว่าหรือพัฒนาฝีมือ
```mermaid
stateDiagram-v2
[*] --> Playing: เริ่มเกม
Playing --> Victory: ทำลายศัตรูทั้งหมด
Playing --> Defeat: ชีวิต = 0
Victory --> MessageDisplay: แสดงข้อความชนะ
Defeat --> MessageDisplay: แสดงข้อความแพ้
MessageDisplay --> WaitingRestart: กด Enter เพื่อดำเนินการต่อ
WaitingRestart --> Resetting: กดปุ่ม Enter
Resetting --> CleanupMemory: ล้างอินเทอร์วัล
CleanupMemory --> ClearEvents: ลบผู้ฟังเหตุการณ์
ClearEvents --> InitializeGame: เริ่มต้นเกมใหม่
InitializeGame --> Playing: เกมใหม่เริ่มต้น
note right of MessageDisplay
ข้อเสนอแนะตามสี:
เขียว = ชนะ
แดง = แพ้
end note
note right of Resetting
รีเซ็ตสถานะทั้งหมด
ป้องกันการรั่วไหลของหน่วยความจำ
end note
```
เกม Tetris เป็นตัวอย่างที่ดีมาก: เมื่อบล็อกของคุณสูงสุดแล้ว คุณสามารถเริ่มเกมใหม่ได้ทันทีโดยไม่ต้องเข้าเมนูซับซ้อน เราจะสร้างระบบเริ่มใหม่ที่รีเซ็ตสถานะเกมให้สะอาดและพาผู้เล่นกลับมาเล่นได้อย่างรวดเร็ว
**ข้อคิด**: นึกถึงเกมที่คุณเคยเล่น พวกมันจบเมื่อไรและพวกเขาให้คุณเริ่มใหม่อย่างไร? อะไรทำให้การเริ่มใหม่รู้สึกราบรื่นหรือหงุดหงิด?
## สิ่งที่คุณจะสร้าง
คุณจะเพิ่มฟีเจอร์สุดท้ายที่เปลี่ยนโปรเจกต์ของคุณให้เป็นประสบการณ์เกมสมบูรณ์ ฟีเจอร์เหล่านี้แยกความแตกต่างระหว่างเกมที่ขัดเกลาและต้นแบบพื้นฐาน
**นี่คือสิ่งที่เราจะเพิ่มวันนี้:**
1. **เงื่อนไขชนะ**: ทำลายศัตรูทั้งหมดและมีการเฉลิมฉลองอย่างเหมาะสม (สมควรแล้ว!)
2. **เงื่อนไขแพ้**: หมดชีวิตและเผชิญหน้ากับหน้าจอแพ้
3. **กลไกเริ่มใหม่**: กด Enter เพื่อเริ่มใหม่ทันที - เพราะเล่นเกมเดียวไม่เคยพอ
4. **การจัดการสถานะ**: เริ่มต้นสะอาดทุกครั้ง - ไม่มีศัตรูหลงเหลือหรือบั๊กแปลกๆ จากเกมก่อนหน้า
## เริ่มต้น
เตรียมสภาพแวดล้อมสำหรับการพัฒนา คุณควรมีไฟล์เกมอวกาศจากบทเรียนก่อนหน้าครบถ้วน
**โปรเจกต์ของคุณควรมีโครงสร้างประมาณนี้:**
```bash
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| life.png
-| index.html
-| app.js
-| package.json
```
**เริ่มเซิร์ฟเวอร์สำหรับพัฒนา:**
```bash
cd your-work
npm start
```
**คำสั่งนี้:**
- รันเซิร์ฟเวอร์บน `http://localhost:5000`
- ให้บริการไฟล์ของคุณอย่างถูกต้อง
- รีเฟรชอัตโนมัติเมื่อคุณมีการเปลี่ยนแปลง
เปิด `http://localhost:5000` บนเบราว์เซอร์และตรวจสอบว่าเกมทำงานได้ คุณควรจะสามารถเคลื่อนที่ ยิง และโต้ตอบกับศัตรูได้ เมื่อตรวจสอบแล้ว เราจะไปทำการใช้งานต่อ
> 💡 **เคล็ดลับโปร**: เพื่อหลีกเลี่ยงการเตือนใน Visual Studio Code ให้ประกาศ `gameLoopId` ที่ด้านบนของไฟล์ด้วย `let gameLoopId;` แทนการประกาศในฟังก์ชัน `window.onload` ซึ่งเป็นแนวปฏิบัติที่ดีใน JavaScript สมัยใหม่
```mermaid
flowchart TD
A["1. การติดตามเงื่อนไข"] --> B["2. ตัวจัดการเหตุการณ์"]
B --> C["3. ค่าคงที่ข้อความ"]
C --> D["4. ควบคุมการเริ่มต้นใหม่"]
D --> E["5. การแสดงข้อความ"]
E --> F["6. รีเซ็ตระบบ"]
G["isHeroDead()\nisEnemiesDead()"] --> A
H["เหตุการณ์การชน\nเหตุการณ์จบเกม"] --> B
I["GAME_END_WIN\nGAME_END_LOSS"] --> C
J["ปุ่ม Enter\nตัวกระตุ้นเริ่มใหม่"] --> D
K["ชัยชนะ/ความพ่ายแพ้\nข้อความที่มีสีแยก"] --> E
L["การทำความสะอาดสถานะ\nการเริ่มต้นใหม่"] --> F
F --> M["🎮 เกมสมบูรณ์"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
style M fill:#e1f5fe
```
## ขั้นตอนการใช้งาน
### ขั้นตอนที่ 1: สร้างฟังก์ชันติดตามเงื่อนไขการจบเกม
เราต้องฟังก์ชันที่ตรวจสอบว่าเกมควรจบเมื่อไร เหมือนเซนเซอร์ของสถานีอวกาศนานาชาติที่คอยตรวจตราระบบสำคัญ ฟังก์ชันเหล่านี้จะตรวจสอบสถานะเกมอย่างต่อเนื่อง
```javascript
function isHeroDead() {
return hero.life <= 0;
}
function isEnemiesDead() {
const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead);
return enemies.length === 0;
}
```
**สิ่งที่เกิดขึ้นใต้เครือง:**
- **ตรวจสอบ** ว่าฮีโร่ของเราหมดชีวิตหรือยัง (เจ็บปวด!)
- **นับ** จำนวนศัตรูที่ยังมีชีวิตและต่อสู้ได้
- **คืนค่า** `true` เมื่อสนามรบปลอดศัตรู
- **ใช้** ลอจิกแบบ true/false ทำให้ง่ายต่อความเข้าใจ
- **กรอง** ผ่านวัตถุเกมทั้งหมดเพื่อหาเหล่าสมาชิกที่รอดชีวิต
### ขั้นตอนที่ 2: อัปเดตตัวจัดการเหตุการณ์สำหรับเงื่อนไขการจบ
ตอนนี้เราจะเชื่อมการตรวจสอบเงื่อนไขเข้ากับระบบเหตุการณ์ของเกม ทุกครั้งที่เกิดการชน เกมจะประเมินว่ามันเป็นเหตุให้จบไหม วิธีนี้ทำให้มีฟีดแบ็กทันทีสำหรับเหตุการณ์สำคัญในเกม
```mermaid
sequenceDiagram
participant Collision
participant GameLogic
participant Conditions
participant EventSystem
participant Display
Collision->>GameLogic: เลเซอร์โดนศัตรู
GameLogic->>GameLogic: ทำลายวัตถุ
GameLogic->>Conditions: ตรวจสอบ isEnemiesDead()
alt ศัตรูทั้งหมดถูกกำจัด
Conditions->>EventSystem: ส่งสัญญาณ GAME_END_WIN
EventSystem->>Display: แสดงข้อความชนะ
else ศัตรูยังเหลือ
Conditions->>GameLogic: ต่อเกม
end
Collision->>GameLogic: ศัตรูชนฮีโร่
GameLogic->>GameLogic: ลดจำนวนชีวิต
GameLogic->>Conditions: ตรวจสอบ isHeroDead()
alt ชีวิต = 0
Conditions->>EventSystem: ส่งสัญญาณ GAME_END_LOSS
EventSystem->>Display: แสดงข้อความแพ้
else ชีวิตยังเหลือ
GameLogic->>Conditions: ตรวจสอบ isEnemiesDead()
alt ศัตรูทั้งหมดถูกกำจัด
Conditions->>EventSystem: ส่งสัญญาณ GAME_END_WIN
end
end
```
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
first.dead = true;
second.dead = true;
hero.incrementPoints();
if (isEnemiesDead()) {
eventEmitter.emit(Messages.GAME_END_WIN);
}
});
eventEmitter.on(Messages.COLLISION_ENEMY_HERO, (_, { enemy }) => {
enemy.dead = true;
hero.decrementLife();
if (isHeroDead()) {
eventEmitter.emit(Messages.GAME_END_LOSS);
return; // การสูญเสียก่อนชัยชนะ
}
if (isEnemiesDead()) {
eventEmitter.emit(Messages.GAME_END_WIN);
}
});
eventEmitter.on(Messages.GAME_END_WIN, () => {
endGame(true);
});
eventEmitter.on(Messages.GAME_END_LOSS, () => {
endGame(false);
});
```
**สิ่งที่เกิดขึ้นที่นี่:**
- **เลเซอร์โดนศัตรู**: ทั้งคู่หายไป คุณได้คะแนน และเราตรวจสอบว่าคุณชนะหรือยัง
- **ศัตรูชนคุณ**: คุณเสียชีวิตหนึ่งชีวิต และเราตรวจสอบว่าคุณยังมีชีวิตอยู่ไหม
- **เรียงลำดับอย่างชาญฉลาด**: เราตรวจสอบการแพ้ก่อน (ไม่มีใครอยากชนะและแพ้ในเวลาเดียวกัน!)
- **ตอบสนองทันที**: ทันทีที่เกิดเหตุสำคัญ เกมจะรับรู้ทันที
### ขั้นตอนที่ 3: เพิ่มค่าคงที่ข้อความใหม่
คุณต้องเพิ่มประเภทข้อความใหม่ในออบเจ็กต์ค่าคงที่ `Messages` ค่าคงที่เหล่านี้ช่วยรักษาความสม่ำเสมอและป้องกันการสะกดผิดในระบบเหตุการณ์ของคุณ
```javascript
GAME_END_LOSS: "GAME_END_LOSS",
GAME_END_WIN: "GAME_END_WIN",
```
**ในข้างต้นเราได้:**
- **เพิ่ม** ค่าคงที่สำหรับเหตุการณ์จบเกมเพื่อความสม่ำเสมอ
- **ใช้** ชื่อที่บรรยายชัดเจนเกี่ยวกับจุดประสงค์ของเหตุการณ์
- **ปฏิบัติตาม** คอนเวนชันการตั้งชื่อเดิมสำหรับประเภทข้อความ
### ขั้นตอนที่ 4: ใช้งานการควบคุมการเริ่มเกมใหม่
ตอนนี้คุณจะเพิ่มการควบคุมผ่านคีย์บอร์ดที่ช่วยให้ผู้เล่นเริ่มเกมใหม่ได้ ปุ่ม Enter เป็นตัวเลือกที่เหมาะสมเพราะมักใช้เพื่อยืนยันการกระทำและเริ่มเกมใหม่
**เพิ่มการตรวจจับปุ่ม Enter ในตัวรับฟังเหตุการณ์ keydown ที่มีอยู่:**
```javascript
else if(evt.key === "Enter") {
eventEmitter.emit(Messages.KEY_EVENT_ENTER);
}
```
**เพิ่มค่าคงที่ข้อความใหม่:**
```javascript
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
```
**สิ่งที่คุณต้องรู้:**
- **ขยาย** ระบบจัดการเหตุการณ์คีย์บอร์ดที่มีอยู่แล้ว
- **ใช้** ปุ่ม Enter เป็นทริกเกอร์เริ่มใหม่เพื่อประสบการณ์ผู้ใช้ที่เข้าใจง่าย
- **ส่ง** เหตุการณ์ที่กำหนดเองซึ่งส่วนอื่นของเกมสามารถฟังได้
- **รักษา** รูปแบบเดียวกับการควบคุมคีย์บอร์ดอื่นๆ
### ขั้นตอนที่ 5: สร้างระบบแสดงข้อความ
เกมของคุณต้องสื่อสารผลลัพธ์ให้ผู้เล่นอย่างชัดเจน เราจะสร้างระบบข้อความที่แสดงสถานะแพ้ชนะด้วยข้อความสีต่างๆ คล้ายกับอินเทอร์เฟซเทอร์มินอลของระบบคอมพิวเตอร์ยุคแรกที่ใช้สีเขียวแสดงความสำเร็จและสีแดงแสดงข้อผิดพลาด
**สร้างฟังก์ชัน `displayMessage()`:**
```javascript
function displayMessage(message, color = "red") {
ctx.font = "30px Arial";
ctx.fillStyle = color;
ctx.textAlign = "center";
ctx.fillText(message, canvas.width / 2, canvas.height / 2);
}
```
**ทีละขั้นตอน สิ่งที่เกิดขึ้น:**
- **ตั้งค่า** ขนาดและฟอนต์เพื่อข้อความที่อ่านง่าย
- **ใช้** พารามิเตอร์สี โดยค่าเริ่มต้นคือ "แดง" สำหรับคำเตือน
- **จัดกึ่งกลาง** ข้อความทั้งแนวนอนและแนวตั้งบนแคนวาส
- **ใช้** พารามิเตอร์ดีฟอลต์ของ JavaScript เพื่อความยืดหยุ่นในสี
- **ใช้** 2D context ของแคนวาสสำหรับการเรนเดอร์ข้อความโดยตรง
**สร้างฟังก์ชัน `endGame()`:**
```javascript
function endGame(win) {
clearInterval(gameLoopId);
// ตั้งค่าการหน่วงเวลาเพื่อให้การเรนเดอร์ที่รอดำเนินการเสร็จสมบูรณ์
setTimeout(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (win) {
displayMessage(
"Victory!!! Pew Pew... - Press [Enter] to start a new game Captain Pew Pew",
"green"
);
} else {
displayMessage(
"You died !!! Press [Enter] to start a new game Captain Pew Pew"
);
}
}, 200)
}
```
**หน้าที่ของฟังก์ชันนี้:**
- **หยุด** การเคลื่อนที่ทั้งหมด - ไม่มีการเคลื่อนที่ของยานหรือเลเซอร์
- **หยุดชั่วครู่** (200ms) เพื่อให้เฟรมสุดท้ายวาดเสร็จ
- **ล้างหน้าจอ** และทาสีดำเพื่อสร้างเอฟเฟกต์ดราม่า
- **แสดง** ข้อความที่ต่างกันสำหรับผู้ชนะและผู้แพ้
- **ใช้สี** เขียวสำหรับดี และแดงสำหรับ... ไม่ค่อยดี
- **บอก** วิธีเริ่มใหม่แก่ผู้เล่นอย่างชัดเจน
### 🔄 **สรุปเชิงการสอน**
**การจัดการสถานะเกม**: ก่อนใช้งานฟังก์ชันรีเซ็ต ให้แน่ใจว่าคุณเข้าใจ:
- ✅ เงื่อนไขจบเกมกำหนดวัตถุประสงค์เพื่อการเล่นเกมได้อย่างไร
- ✅ ทำไมฟีดแบ็กด้วยภาพถึงสำคัญสำหรับความเข้าใจของผู้เล่น
- ✅ ความสำคัญของการทำความสะอาดที่เหมาะสมในการป้องกันหน่วยความจำรั่วไหล
- ✅ สถาปัตยกรรมขับเคลื่อนด้วยเหตุการณ์ช่วยให้เปลี่ยนสถานะได้อย่างเรียบร้อยอย่างไร
**ทดสอบตนเองอย่างรวดเร็ว**: จะเกิดอะไรขึ้นหากคุณไม่ลบตัวรับฟังเหตุการณ์เมื่อรีเซ็ต?
*คำตอบ: เกิดหน่วยความจำรั่วและตัวจัดการเหตุการณ์ซ้ำซ้อนทำให้เกมทำงานไม่คาดคิด*
**หลักการออกแบบเกม**: ตอนนี้คุณกำลังใช้งาน:
- **วัตถุประสงค์ที่ชัดเจน**: ผู้เล่นรู้ชัดเจนว่าสิ่งใดคือความสำเร็จและความล้มเหลว
- **การตอบสนองทันที**: การเปลี่ยนแปลงสถานะเกมสื่อสารให้รู้ทันที
- **การควบคุมของผู้ใช้**: ผู้เล่นสามารถเริ่มใหม่เมื่อพร้อม
- **ความน่าเชื่อถือของระบบ**: การทำความสะอาดที่เหมาะสมป้องกันบั๊กและปัญหาประสิทธิภาพ
### ขั้นตอนที่ 6: ใช้งานฟังก์ชันรีเซ็ตเกม
ระบบรีเซ็ตต้องทำความสะอาดสถานะเกมทั้งหมดและเริ่มเซสชันเกมใหม่เพื่อให้ผู้เล่นเริ่มต้นใหม่อย่างสะอาด ไม่มีข้อมูลตกค้างจากเกมก่อนหน้า
**สร้างฟังก์ชัน `resetGame()`:**
```javascript
function resetGame() {
if (gameLoopId) {
clearInterval(gameLoopId);
eventEmitter.clear();
initGame();
gameLoopId = setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawPoints();
drawLife();
updateGameObjects();
drawGameObjects(ctx);
}, 100);
}
}
```
**มาทำความเข้าใจแต่ละส่วน:**
- **ตรวจสอบ** ว่าตอนนี้มี game loop ทำงานอยู่หรือไม่ก่อนรีเซ็ต
- **ลบ** game loop ที่มีอยู่เพื่อหยุดกิจกรรมเกมทั้งหมด
- **ลบ** ตัวรับฟังเหตุการณ์ทั้งหมดเพื่อป้องกันหน่วยความจำรั่ว
- **เริ่มใหม่** สถานะเกมด้วยออบเจ็กต์และตัวแปรใหม่
- **เริ่ม** game loop ใหม่พร้อมฟังก์ชันที่จำเป็นทั้งหมด
- **ใช้** เวลาหน่วง 100ms เดิมเพื่อประสิทธิภาพเกมที่คงที่
**เพิ่มตัวจัดการเหตุการณ์กด Enter ในฟังก์ชัน `initGame()`:**
```javascript
eventEmitter.on(Messages.KEY_EVENT_ENTER, () => {
resetGame();
});
```
**เพิ่มเมธอด `clear()` ให้คลาส EventEmitter ของคุณ:**
```javascript
clear() {
this.listeners = {};
}
```
**จุดสำคัญที่ต้องจำ:**
- **เชื่อม** การกดปุ่ม Enter กับฟังก์ชันรีเซ็ตเกม
- **ลงทะเบียน** ตัวรับฟังเหตุการณ์นี้ในตอนเริ่มเกม
- **ให้วิธีล้างตัวรับฟังทั้งหมดเมื่อรีเซ็ต**
- **ป้องกัน** หน่วยความจำรั่วโดยการล้างตัวจัดการเหตุการณ์ระหว่างเกม
- **รีเซ็ต** ออบเจ็กต์ listeners ให้เป็นสถานะว่างเพื่อเริ่มต้นใหม่
## ยินดีด้วย! 🎉
👽 💥 🚀 คุณสร้างเกมสมบูรณ์ตั้งแต่เริ่มต้นได้สำเร็จ เหมือนนักโปรแกรมเมอร์ที่สร้างวิดีโอเกมแรกในยุค 1970 คุณได้แปลงโค้ดเป็นประสบการณ์ที่โต้ตอบได้พร้อมกลไกเกมและฟีดแบ็กของผู้ใช้ที่เหมาะสมแล้ว 🚀 💥 👽
**สิ่งที่คุณทำสำเร็จ:**
- **ใช้งาน** เงื่อนไขชนะและแพ้อย่างครบถ้วนพร้อมฟีดแบ็กของผู้ใช้
- **สร้าง** ระบบเริ่มเกมใหม่ที่ราบรื่นสำหรับการเล่นต่อเนื่อง
- **ออกแบบ** การสื่อสารสถานะเกมด้วยภาพที่ชัดเจน
- **จัดการ** การเปลี่ยนสถานะเกมและการทำความสะอาดซับซ้อน
- **รวม** ส่วนประกอบทั้งหมดเข้าด้วยกันเป็นเกมที่เล่นได้อย่างลงตัว
### 🔄 **สรุปเชิงการสอน**
**ระบบพัฒนาเกมครบวงจร**: เฉลิมฉลองความชำนาญในการพัฒนาเกมครบถ้วน:
- ✅ เงื่อนไขจบเกมสร้างประสบการณ์ที่น่าพึงพอใจอย่างไร
- ✅ ทำไมการจัดการสถานะที่เหมาะสมจึงสำคัญต่อความเสถียรของเกม
- ✅ ฟีดแบ็กด้วยภาพช่วยเพิ่มความเข้าใจของผู้เล่นอย่างไร
- ✅ ระบบเริ่มใหม่ช่วยรักษาผู้เล่นไว้อย่างไร
**ความชำนาญระบบ**: เกมที่สมบูรณ์ของคุณแสดงให้เห็น:
- **พัฒนาเกมเต็มรูปแบบ**: ตั้งแต่กราฟิก อินพุต ไปจนถึงการจัดการสถานะ
- **สถาปัตยกรรมมืออาชีพ**: ระบบขับเคลื่อนด้วยเหตุการณ์ที่ทำความสะอาดได้ดี
- **ออกแบบประสบการณ์ผู้ใช้**: ฟีดแบ็กชัดเจนและควบคุมได้อย่างเข้าใจง่าย
- **เพิ่มประสิทธิภาพ**: การเรนเดอร์และจัดการหน่วยความจำอย่างมีประสิทธิภาพ
- **ความสมบูรณ์และขัดเกลา**: รายละเอียดทั้งหมดที่ทำให้เกมรู้สึกสมบูรณ์
**ทักษะพร้อมใช้งานในอุตสาหกรรม**: คุณใช้งาน:
- **สถาปัตยกรรมเกมลูป**: ระบบเรียลไทม์ที่มีประสิทธิภาพคงที่
- **การเขียนโปรแกรมขับเคลื่อนด้วยเหตุการณ์**: ระบบแยกกันที่สามารถขยายได้ดี
- **การจัดการสถานะ**: การจัดการข้อมูลซับซ้อนและวงจรชีวิต
- **ออกแบบส่วนติดต่อผู้ใช้**: สื่อสารชัดเจนและควบคุมตอบสนอง
- **การทดสอบและดีบัก**: การพัฒนาแบบวนซ้ำและแก้ปัญหา
### ⚡ **สิ่งที่คุณสามารถทำได้ใน 5 นาทีถัดไป**
- [ ] เล่นเกมสมบูรณ์และทดสอบทุกเงื่อนไขชนะและแพ้
- [ ] ทดลองเปลี่ยนพารามิเตอร์เงื่อนไขจบเกมต่างๆ
- [ ] เพิ่มคำสั่ง console.log เพื่อติดตามสถานะเกม
- [ ] แชร์เกมของคุณกับเพื่อนและรับคำติชม
### 🎯 **สิ่งที่คุณสามารถทำได้ในชั่วโมงนี้**
- [ ] ทำแบบทดสอบหลังเรียนและสะท้อนเส้นทางพัฒนาของคุณ
- [ ] เพิ่มเอฟเฟกต์เสียงสำหรับสถานะแพ้และชนะ
- [ ] ใช้งานเงื่อนไขจบเกมเพิ่มเติม เช่น จำกัดเวลา หรือภารกิจโบนัส
- [ ] สร้างระดับความยากต่างๆ ด้วยจำนวนศัตรูที่แตกต่างกัน
- [ ] ขัดเกลาการแสดงผลด้วยฟอนต์และสีที่ดียิ่งขึ้น
### 📅 **การฝึกฝนพัฒนาเกมตลอดสัปดาห์ของคุณ**
- [ ] ทำเกมอวกาศขั้นสูงที่มีหลายเลเวลและการพัฒนา
- [ ] เพิ่มฟีเจอร์ขั้นสูง เช่น power-ups, ศัตรูประเภทต่างๆ และอาวุธพิเศษ
- [ ] สร้างระบบคะแนนสูงที่เก็บข้อมูลได้ถาวร
- [ ] ออกแบบอินเทอร์เฟซสำหรับเมนู การตั้งค่า และตัวเลือกเกม
- [ ] ปรับปรุงประสิทธิภาพสำหรับอุปกรณ์และเบราว์เซอร์ต่างๆ
- [ ] เปิดเล่นเกมออนไลน์และแชร์กับชุมชน
### 🌟 **สายอาชีพพัฒนาเกมของคุณตลอดหนึ่งเดือน**
- [ ] สร้างเกมหลายเกมที่สมบูรณ์แบบโดยสำรวจแนวเกมและกลไกที่แตกต่างกัน
- [ ] เรียนรู้เฟรมเวิร์กพัฒนาเกมขั้นสูงอย่าง Phaser หรือ Three.js
- [ ] ร่วมช่วยพัฒนาโปรเจกต์เกมโอเพนซอร์ส
- [ ] ศึกษาหลักการออกแบบเกมและจิตวิทยาผู้เล่น
- [ ] สร้างผลงานเพื่อแสดงทักษะการพัฒนาเกมของคุณ
- [ ] ติดต่อสื่อสารกับชุมชนผู้พัฒนาเกมและเรียนรู้ต่อเนื่อง
## 🎯 ไทม์ไลน์ความเชี่ยวชาญการพัฒนาเกมของคุณ
```mermaid
timeline
title ความก้าวหน้าในการเรียนรู้การพัฒนาเกมครบถ้วน
section พื้นฐาน (บทเรียนที่ 1-2)
สถาปัตยกรรมเกม: โครงสร้างโปรเจกต์
: การจัดการทรัพยากร
: พื้นฐานแคนวาส
: ระบบเหตุการณ์
section ระบบปฏิสัมพันธ์ (บทเรียนที่ 3-4)
การควบคุมผู้เล่น: การจัดการอินพุต
: กลไกการเคลื่อนไหว
: การตรวจจับการชน
: การจำลองฟิสิกส์
section กลไกเกม (บทเรียนที่ 5)
ระบบตอบสนอง: กลไกการให้คะแนน
: การจัดการชีวิต
: การสื่อสารด้วยภาพ
: แรงจูงใจผู้เล่น
section การจบเกม (บทเรียนที่ 6)
การขัดเกลา & การไหล: เงื่อนไขการสิ้นสุด
: การจัดการสถานะ
: ระบบเริ่มต้นใหม่
: ประสบการณ์ผู้ใช้
section ฟีเจอร์ขั้นสูง (1 สัปดาห์)
ทักษะการเสริม: การผสานเสียง
: เอฟเฟกต์ภาพ
: ความก้าวหน้าของระดับ
: การเพิ่มประสิทธิภาพ
section การพัฒนาเชิงมืออาชีพ (1 เดือน)
ความพร้อมในอุตสาหกรรม: ความเชี่ยวชาญในเฟรมเวิร์ก
: การทำงานเป็นทีม
: การพัฒนาผลงาน
: การมีส่วนร่วมกับชุมชน
section ความก้าวหน้าในอาชีพ (3 เดือน)
ความชำนาญพิเศษ: เอนจินเกมขั้นสูง
: การนำไปใช้บนแพลตฟอร์ม
: กลยุทธ์การสร้างรายได้
: การสร้างเครือข่ายในอุตสาหกรรม
```
### 🛠️ สรุปชุดเครื่องมือพัฒนาเกมครบวงจรของคุณ
หลังจากจบซีรีส์เกมอวกาศทั้งหมดนี้ คุณได้เชี่ยวชาญในเรื่อง:
- **สถาปัตยกรรมเกม**: ระบบขับเคลื่อนด้วยเหตุการณ์, วงจรเกม, และการจัดการสถานะ
- **การเขียนโปรแกรมกราฟิก**: Canvas API, การแสดง sprite, และเอฟเฟกต์ภาพ
- **ระบบอินพุต**: การจัดการคีย์บอร์ด, ตรวจจับการชน, และการควบคุมที่ตอบสนอง
- **การออกแบบเกม**: การตอบรับผู้เล่น, ระบบความก้าวหน้า, และกลไกการดึงดูด
- **การเพิ่มประสิทธิภาพ**: การเรนเดอร์ที่มีประสิทธิผล, การจัดการหน่วยความจำ, และคุมเฟรมเรต
- **ประสบการณ์ผู้ใช้**: การสื่อสารที่ชัดเจน, การควบคุมที่เข้าใจง่าย, และรายละเอียดงานขัดเกลา
- **รูปแบบการพัฒนาเชิงมืออาชีพ**: โค้ดที่สะอาด, เทคนิคดีบัก, และการจัดการโปรเจกต์
**การประยุกต์ใช้ในโลกจริง**: ทักษะการพัฒนาเกมของคุณนำไปใช้ได้โดยตรงกับ:
- **แอปพลิเคชันเว็บแบบโต้ตอบ**: อินเทอร์เฟซที่มีการไดนามิกและระบบเรียลไทม์
- **การแสดงข้อมูล**: แผนภูมิที่มีแอนิเมชันและกราฟิกแบบโต้ตอบ
- **เทคโนโลยีเพื่อการศึกษา**: การทำเกมเป็นบทเรียนและประสบการณ์การเรียนรู้ที่น่าสนใจ
- **การพัฒนาโมบาย**: การโต้ตอบด้วยสัมผัสและการเพิ่มประสิทธิภาพ
- **ซอฟต์แวร์จำลองสถานการณ์**: เอนจินฟิสิกส์และการจำลองแบบเรียลไทม์
- **อุตสาหกรรมสร้างสรรค์**: ศิลปะโต้ตอบ, ความบันเทิง, และประสบการณ์ดิจิทัล
**ทักษะเชิงมืออาชีพที่ได้รับ**: ตอนนี้คุณสามารถ:
- **ออกแบบสถาปัตยกรรม** ระบบโต้ตอบที่ซับซ้อนตั้งแต่เริ่มต้น
- **ดีบัก** แอปพลิเคชันแบบเรียลไทม์ด้วยวิธีการเป็นระบบ
- **เพิ่มประสิทธิภาพ** เพื่อประสบการณ์ใช้งานที่ราบรื่น
- **ออกแบบ** อินเทอร์เฟซและรูปแบบการโต้ตอบที่น่าสนใจ
- **ร่วมมือ** ในโปรเจกต์เชิงเทคนิคได้อย่างมีประสิทธิภาพโดยจัดการโค้ดดี
**แนวคิดพัฒนาการเกมที่เชี่ยวชาญ**:
- **ระบบแบบเรียลไทม์**: วงจรเกม, การควบคุมเฟรมเรต, และประสิทธิภาพ
- **สถาปัตยกรรมขับเคลื่อนด้วยเหตุการณ์**: ระบบแยกส่วนและกระบวนการส่งข้อความ
- **การจัดการสถานะ**: การจัดการข้อมูลซับซ้อนและวงจรชีวิต
- **การเขียนโปรแกรมอินเทอร์เฟซผู้ใช้**: กราฟิก Canvas และการออกแบบตอบสนอง
- **ทฤษฎีการออกแบบเกม**: จิตวิทยาผู้เล่นและกลไกการดึงดูด
**ระดับถัดไป**: คุณพร้อมที่จะสำรวจเฟรมเวิร์กเกมขั้นสูง กราฟิก 3D ระบบผู้เล่นหลายคน หรือเปลี่ยนไปสู่บทบาทนักพัฒนาเกมมืออาชีพ!
🌟 **สำเร็จแล้ว**: คุณได้ทำเสร็จสิ้นเส้นทางพัฒนาเกมเต็มรูปแบบและสร้างประสบการณ์โต้ตอบคุณภาพมืออาชีพขึ้นมาได้ตั้งแต่ต้น!
**ยินดีต้อนรับสู่ชุมชนผู้พัฒนาเกม!** 🎮✨
## ความท้าทาย GitHub Copilot Agent 🚀
ใช้โหมด Agent เพื่อทำความท้าทายต่อไปนี้ให้สำเร็จ:
**คำอธิบาย:** ปรับปรุงเกมอวกาศโดยเพิ่มระบบความก้าวหน้าระดับที่มีความยากเพิ่มขึ้นพร้อมฟีเจอร์โบนัส
**พรอมต์:** สร้างระบบเกมอวกาศหลายระดับ โดยแต่ละระดับจะมีเรือศัตรูมากขึ้นด้วยความเร็วและพลังชีวิตที่เพิ่มขึ้น เพิ่มตัวคูณคะแนนที่เพิ่มขึ้นตามระดับ และเพิ่ม power-ups (เช่น ยิงเร็วหรือเกราะ) ที่สุ่มปรากฏเมื่อศัตรูถูกทำลาย รวมโบนัสจบระดับและแสดงระดับปัจจุบันบนหน้าจอพร้อมคะแนนและชีวิตเดิม
เรียนรู้เพิ่มเติมเกี่ยวกับ [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) ที่นี่
## 🚀 ความท้าทายเสริม (ไม่บังคับ)
**เพิ่มเสียงในเกมของคุณ**: เพิ่มประสบการณ์เล่นเกมของคุณด้วยการเพิ่มเอฟเฟกต์เสียง! พิจารณาเพิ่มเสียงสำหรับ:
- **เสียงเลเซอร์** เมื่อผู้เล่นยิง
- **เสียงศัตรูถูกทำลาย** เมื่อเรือโดนโจมตี
- **เสียงฮีโร่ถูกโจมตี** เมื่อผู้เล่นได้รับความเสียหาย
- **เสียงเพลงชัยชนะ** เมื่อชนะเกม
- **เสียงพ่ายแพ้** เมื่อแพ้เกม
**ตัวอย่างการใช้งานเสียง:**
```javascript
// สร้างวัตถุเสียง
const laserSound = new Audio('assets/laser.wav');
const explosionSound = new Audio('assets/explosion.wav');
// เล่นเสียงในระหว่างเหตุการณ์เกม
function playLaserSound() {
laserSound.currentTime = 0; // รีเซ็ตไปที่ต้นฉบับ
laserSound.play();
}
```
**สิ่งที่ควรรู้:**
- **สร้าง** ออบเจ็กต์เสียงสำหรับเอฟเฟกต์เสียงต่างๆ
- **รีเซ็ต** `currentTime` เพื่อให้เล่นเสียงซ้ำได้อย่างรวดเร็ว
- **จัดการ** นโยบายอัตโนมัติเล่นเสียงของเบราว์เซอร์โดยเรียกเสียงจากปฏิสัมพันธ์ของผู้ใช้
- **ควบคุม** ความดังและเวลาของเสียงเพื่อประสบการณ์เล่นเกมที่ดีขึ้น
> 💡 **แหล่งเรียนรู้**: สำรวจ [audio sandbox](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) นี้เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับการใช้งานเสียงในการพัฒนาเกม JavaScript
## แบบทดสอบหลังบรรยาย
[แบบทดสอบหลังบรรยาย](https://ff-quizzes.netlify.app/web/quiz/40)
## ทบทวน & ศึกษาด้วยตนเอง
ภารกิจของคุณคือการสร้างเกมตัวอย่างใหม่ ดังนั้นลองสำรวจเกมน่าสนใจต่าง ๆ เพื่อดูว่าคุณอยากสร้างเกมแบบไหน
## งานมอบหมาย
[สร้างเกมตัวอย่าง](assignment.md)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**ข้อจำกัดความรับผิดชอบ**:
เอกสารฉบับนี้ได้รับการแปลโดยใช้บริการแปลภาษาด้วย AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้เราจะพยายามให้ความถูกต้องสูงสุด แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้องได้ เอกสารต้นฉบับในภาษาดั้งเดิมถือเป็นแหล่งข้อมูลที่เชื่อถือได้ที่สุด สำหรับข้อมูลที่มีความสำคัญ แนะนำให้ใช้บริการแปลโดยมืออาชีพ เรายินดีรับผิดชอบในความเข้าใจผิดหรือการตีความที่ผิดพลาดใด ๆ ที่อาจเกิดขึ้นจากการใช้การแปลนี้
<!-- CO-OP TRANSLATOR DISCLAIMER END -->