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/4-collision-detection/README.md

311 lines
19 KiB

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "2e83e38c35dc003f046d7cc0bbfd4920",
"translation_date": "2025-08-26T22:02:11+00:00",
"source_file": "6-space-game/4-collision-detection/README.md",
"language_code": "th"
}
-->
# สร้างเกมอวกาศ ตอนที่ 4: เพิ่มเลเซอร์และตรวจจับการชน
## แบบทดสอบก่อนเรียน
[แบบทดสอบก่อนเรียน](https://ff-quizzes.netlify.app/web/quiz/35)
ในบทเรียนนี้ คุณจะได้เรียนรู้วิธีการยิงเลเซอร์ด้วย JavaScript! เราจะเพิ่มสองสิ่งลงในเกมของเรา:
- **เลเซอร์**: เลเซอร์นี้จะถูกยิงจากยานของฮีโร่และเคลื่อนที่ขึ้นไปในแนวตั้ง
- **การตรวจจับการชน**: เป็นส่วนหนึ่งของการเพิ่มความสามารถในการ *ยิง* เราจะเพิ่มกฎของเกมที่น่าสนใจ:
- **เลเซอร์ชนศัตรู**: ศัตรูจะตายเมื่อถูกเลเซอร์
- **เลเซอร์ชนขอบบนของหน้าจอ**: เลเซอร์จะถูกทำลายเมื่อชนขอบบนของหน้าจอ
- **ศัตรูชนฮีโร่**: ศัตรูและฮีโร่จะถูกทำลายเมื่อชนกัน
- **ศัตรูชนขอบล่างของหน้าจอ**: ศัตรูและฮีโร่จะถูกทำลายเมื่อศัตรูชนขอบล่างของหน้าจอ
สรุปคือ คุณ -- *ฮีโร่* -- ต้องยิงศัตรูทั้งหมดด้วยเลเซอร์ก่อนที่พวกมันจะเคลื่อนที่ไปถึงขอบล่างของหน้าจอ
✅ ลองค้นคว้าเกี่ยวกับเกมคอมพิวเตอร์เกมแรกที่เคยถูกสร้างขึ้น มันมีฟังก์ชันอะไรบ้าง?
มาร่วมเป็นฮีโร่กันเถอะ!
## การตรวจจับการชน
เราจะตรวจจับการชนได้อย่างไร? เราต้องคิดว่าออบเจ็กต์ในเกมของเราเป็นรูปสี่เหลี่ยมที่เคลื่อนที่ไปมา ทำไมถึงเป็นเช่นนั้น? เพราะภาพที่ใช้ในการวาดออบเจ็กต์ในเกมเป็นรูปสี่เหลี่ยม: มันมี `x`, `y`, `width` และ `height`
ถ้ารูปสี่เหลี่ยมสองรูป เช่น ฮีโร่และศัตรู *ตัดกัน* นั่นคือการชน สิ่งที่ควรเกิดขึ้นหลังจากนั้นขึ้นอยู่กับกฎของเกม ในการสร้างการตรวจจับการชน คุณจำเป็นต้องมีสิ่งต่อไปนี้:
1. วิธีการสร้างตัวแทนรูปสี่เหลี่ยมของออบเจ็กต์ในเกม เช่นนี้:
```javascript
rectFromGameObject() {
return {
top: this.y,
left: this.x,
bottom: this.y + this.height,
right: this.x + this.width
}
}
```
2. ฟังก์ชันเปรียบเทียบ ฟังก์ชันนี้อาจมีลักษณะดังนี้:
```javascript
function intersectRect(r1, r2) {
return !(r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top);
}
```
## เราจะทำลายสิ่งต่าง ๆ ได้อย่างไร
ในการทำลายสิ่งต่าง ในเกม คุณต้องแจ้งให้เกมทราบว่าไม่ควรวาดออบเจ็กต์นี้อีกในลูปเกมที่ทำงานในช่วงเวลาที่กำหนด วิธีหนึ่งคือการทำเครื่องหมายออบเจ็กต์ในเกมว่า *ตาย* เมื่อมีบางสิ่งเกิดขึ้น เช่นนี้:
```javascript
// collision happened
enemy.dead = true
```
จากนั้นคุณสามารถจัดการกับออบเจ็กต์ที่ *ตาย* ก่อนที่จะวาดหน้าจอใหม่ เช่นนี้:
```javascript
gameObjects = gameObject.filter(go => !go.dead);
```
## เราจะยิงเลเซอร์ได้อย่างไร
การยิงเลเซอร์หมายถึงการตอบสนองต่อเหตุการณ์กดปุ่มและสร้างออบเจ็กต์ที่เคลื่อนที่ในทิศทางหนึ่ง ดังนั้นเราจำเป็นต้องดำเนินการตามขั้นตอนต่อไปนี้:
1. **สร้างออบเจ็กต์เลเซอร์**: จากด้านบนของยานฮีโร่ ซึ่งเมื่อถูกสร้างขึ้นจะเริ่มเคลื่อนที่ขึ้นไปยังขอบบนของหน้าจอ
2. **เชื่อมโค้ดกับเหตุการณ์กดปุ่ม**: เราต้องเลือกปุ่มบนคีย์บอร์ดที่แทนการยิงเลเซอร์ของผู้เล่น
3. **สร้างออบเจ็กต์ในเกมที่ดูเหมือนเลเซอร์** เมื่อกดปุ่ม
## การตั้งค่าคูลดาวน์สำหรับเลเซอร์
เลเซอร์ต้องยิงทุกครั้งที่คุณกดปุ่ม เช่น *space* เพื่อป้องกันไม่ให้เกมสร้างเลเซอร์มากเกินไปในเวลาสั้น เราจำเป็นต้องแก้ไขสิ่งนี้ วิธีแก้ไขคือการตั้งค่าที่เรียกว่า *คูลดาวน์* ซึ่งเป็นตัวจับเวลา ที่ทำให้เลเซอร์ยิงได้ในช่วงเวลาที่กำหนด คุณสามารถทำได้ดังนี้:
```javascript
class Cooldown {
constructor(time) {
this.cool = false;
setTimeout(() => {
this.cool = true;
}, time)
}
}
class Weapon {
constructor {
}
fire() {
if (!this.cooldown || this.cooldown.cool) {
// produce a laser
this.cooldown = new Cooldown(500);
} else {
// do nothing - it hasn't cooled down yet.
}
}
}
```
อ้างอิงบทเรียนที่ 1 ในซีรีส์เกมอวกาศเพื่อทบทวนเกี่ยวกับ *คูลดาวน์*
## สิ่งที่ต้องสร้าง
คุณจะใช้โค้ดที่มีอยู่ (ซึ่งคุณควรทำความสะอาดและปรับปรุงแล้ว) จากบทเรียนก่อนหน้า และขยายมันออกไป คุณสามารถเริ่มต้นด้วยโค้ดจากตอนที่ II หรือใช้โค้ดที่ [Part III- starter](../../../../../../../../../your-work)
> เคล็ดลับ: เลเซอร์ที่คุณจะทำงานด้วยนั้นอยู่ในโฟลเดอร์ assets ของคุณแล้วและถูกอ้างอิงโดยโค้ดของคุณ
- **เพิ่มการตรวจจับการชน** เมื่อเลเซอร์ชนกับบางสิ่ง กฎต่อไปนี้ควรนำมาใช้:
1. **เลเซอร์ชนศัตรู**: ศัตรูจะตายเมื่อถูกเลเซอร์
2. **เลเซอร์ชนขอบบนของหน้าจอ**: เลเซอร์จะถูกทำลายเมื่อชนขอบบนของหน้าจอ
3. **ศัตรูชนฮีโร่**: ศัตรูและฮีโร่จะถูกทำลายเมื่อชนกัน
4. **ศัตรูชนขอบล่างของหน้าจอ**: ศัตรูและฮีโร่จะถูกทำลายเมื่อศัตรูชนขอบล่างของหน้าจอ
## ขั้นตอนที่แนะนำ
ค้นหาไฟล์ที่ถูกสร้างไว้ให้คุณในโฟลเดอร์ `your-work` มันควรมีสิ่งต่อไปนี้:
```bash
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| index.html
-| app.js
-| package.json
```
เริ่มต้นโปรเจกต์ของคุณในโฟลเดอร์ `your_work` โดยพิมพ์:
```bash
cd your-work
npm start
```
คำสั่งด้านบนจะเริ่ม HTTP Server ที่อยู่ `http://localhost:5000` เปิดเบราว์เซอร์และใส่ที่อยู่นั้น ตอนนี้มันควรแสดงฮีโร่และศัตรูทั้งหมด แต่ยังไม่มีอะไรเคลื่อนไหว - ยังไม่ถึงเวลา :).
### เพิ่มโค้ด
1. **ตั้งค่าตัวแทนรูปสี่เหลี่ยมของออบเจ็กต์ในเกม เพื่อจัดการการชน** โค้ดด้านล่างช่วยให้คุณสร้างตัวแทนรูปสี่เหลี่ยมของ `GameObject` แก้ไขคลาส GameObject ของคุณเพื่อเพิ่มโค้ดนี้:
```javascript
rectFromGameObject() {
return {
top: this.y,
left: this.x,
bottom: this.y + this.height,
right: this.x + this.width,
};
}
```
2. **เพิ่มโค้ดที่ตรวจสอบการชน** นี่จะเป็นฟังก์ชันใหม่ที่ทดสอบว่ารูปสี่เหลี่ยมสองรูปตัดกันหรือไม่:
```javascript
function intersectRect(r1, r2) {
return !(
r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top
);
}
```
3. **เพิ่มความสามารถในการยิงเลเซอร์**
1. **เพิ่มข้อความเหตุการณ์กดปุ่ม** ปุ่ม *space* ควรสร้างเลเซอร์ที่อยู่เหนือยานฮีโร่ เพิ่มค่าคงที่สามตัวในออบเจ็กต์ Messages:
```javascript
KEY_EVENT_SPACE: "KEY_EVENT_SPACE",
COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER",
COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
```
1. **จัดการปุ่ม space** แก้ไขฟังก์ชัน `window.addEventListener` keyup เพื่อจัดการปุ่ม space:
```javascript
} else if(evt.keyCode === 32) {
eventEmitter.emit(Messages.KEY_EVENT_SPACE);
}
```
1. **เพิ่ม listeners** แก้ไขฟังก์ชัน `initGame()` เพื่อให้แน่ใจว่าฮีโร่สามารถยิงได้เมื่อกดปุ่ม space:
```javascript
eventEmitter.on(Messages.KEY_EVENT_SPACE, () => {
if (hero.canFire()) {
hero.fire();
}
```
และเพิ่มฟังก์ชัน `eventEmitter.on()` ใหม่เพื่อจัดการพฤติกรรมเมื่อศัตรูชนกับเลเซอร์:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
first.dead = true;
second.dead = true;
})
```
1. **เคลื่อนย้ายออบเจ็กต์** ให้แน่ใจว่าเลเซอร์เคลื่อนที่ไปยังขอบบนของหน้าจออย่างค่อยเป็นค่อยไป คุณจะสร้างคลาส Laser ใหม่ที่ขยาย `GameObject` เหมือนที่คุณเคยทำมาก่อน:
```javascript
class Laser extends GameObject {
constructor(x, y) {
super(x,y);
(this.width = 9), (this.height = 33);
this.type = 'Laser';
this.img = laserImg;
let id = setInterval(() => {
if (this.y > 0) {
this.y -= 15;
} else {
this.dead = true;
clearInterval(id);
}
}, 100)
}
}
```
1. **จัดการการชน** ใช้กฎการชนสำหรับเลเซอร์ เพิ่มฟังก์ชัน `updateGameObjects()` ที่ทดสอบออบเจ็กต์ที่ชนกัน:
```javascript
function updateGameObjects() {
const enemies = gameObjects.filter(go => go.type === 'Enemy');
const lasers = gameObjects.filter((go) => go.type === "Laser");
// laser hit something
lasers.forEach((l) => {
enemies.forEach((m) => {
if (intersectRect(l.rectFromGameObject(), m.rectFromGameObject())) {
eventEmitter.emit(Messages.COLLISION_ENEMY_LASER, {
first: l,
second: m,
});
}
});
});
gameObjects = gameObjects.filter(go => !go.dead);
}
```
อย่าลืมเพิ่ม `updateGameObjects()` ลงในลูปเกมของคุณใน `window.onload`
4. **ตั้งค่าคูลดาวน์** สำหรับเลเซอร์ เพื่อให้มันยิงได้ในช่วงเวลาที่กำหนด
สุดท้าย แก้ไขคลาส Hero เพื่อให้สามารถตั้งค่าคูลดาวน์ได้:
```javascript
class Hero extends GameObject {
constructor(x, y) {
super(x, y);
(this.width = 99), (this.height = 75);
this.type = "Hero";
this.speed = { x: 0, y: 0 };
this.cooldown = 0;
}
fire() {
gameObjects.push(new Laser(this.x + 45, this.y - 10));
this.cooldown = 500;
let id = setInterval(() => {
if (this.cooldown > 0) {
this.cooldown -= 100;
} else {
clearInterval(id);
}
}, 200);
}
canFire() {
return this.cooldown === 0;
}
}
```
ตอนนี้ เกมของคุณมีฟังก์ชันบางอย่างแล้ว! คุณสามารถเคลื่อนที่ด้วยปุ่มลูกศร ยิงเลเซอร์ด้วยปุ่ม space และศัตรูจะหายไปเมื่อคุณยิงพวกมัน ยอดเยี่ยมมาก!
---
## 🚀 ความท้าทาย
เพิ่มเอฟเฟกต์ระเบิด! ลองดูที่ทรัพยากรเกมใน [Space Art repo](../../../../6-space-game/solution/spaceArt/readme.txt) และลองเพิ่มเอฟเฟกต์ระเบิดเมื่อเลเซอร์ชนเอเลี่ยน
## แบบทดสอบหลังเรียน
[แบบทดสอบหลังเรียน](https://ff-quizzes.netlify.app/web/quiz/36)
## ทบทวนและศึกษาด้วยตัวเอง
ทดลองปรับช่วงเวลาในเกมของคุณจนถึงตอนนี้ จะเกิดอะไรขึ้นเมื่อคุณเปลี่ยนมัน? อ่านเพิ่มเติมเกี่ยวกับ [เหตุการณ์จับเวลาของ JavaScript](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/)
## งานที่ได้รับมอบหมาย
[สำรวจการชน](assignment.md)
---
**ข้อจำกัดความรับผิดชอบ**:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้