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.
426 lines
30 KiB
426 lines
30 KiB
<!--
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
{
|
|
"original_hash": "4b1d441cfd31924084956000c0fee5a5",
|
|
"translation_date": "2025-10-23T21:20:14+00:00",
|
|
"source_file": "6-space-game/4-collision-detection/README.md",
|
|
"language_code": "th"
|
|
}
|
|
-->
|
|
# สร้างเกมอวกาศ ตอนที่ 4: เพิ่มเลเซอร์และตรวจจับการชนกัน
|
|
|
|
## แบบทดสอบก่อนเรียน
|
|
|
|
[แบบทดสอบก่อนเรียน](https://ff-quizzes.netlify.app/web/quiz/35)
|
|
|
|
ลองนึกถึงช่วงเวลาที่ลุคใช้ตอร์ปิโดโปรตอนยิงเข้าช่องไอเสียของดาวมรณะใน Star Wars การตรวจจับการชนกันที่แม่นยำนี้เปลี่ยนชะตากรรมของกาแล็กซี่! ในเกม การตรวจจับการชนกันทำงานในลักษณะเดียวกัน - มันจะกำหนดว่าเมื่อใดที่วัตถุมีปฏิสัมพันธ์และจะเกิดอะไรขึ้นต่อไป
|
|
|
|
ในบทเรียนนี้ คุณจะเพิ่มอาวุธเลเซอร์ในเกมอวกาศของคุณและนำการตรวจจับการชนกันมาใช้ เช่นเดียวกับที่นักวางแผนภารกิจของ NASA คำนวณวิถีของยานอวกาศเพื่อหลีกเลี่ยงเศษซาก คุณจะได้เรียนรู้วิธีตรวจจับเมื่อวัตถุในเกมตัดกัน เราจะทำให้มันง่ายขึ้นด้วยการแบ่งเป็นขั้นตอนที่จัดการได้
|
|
|
|
เมื่อจบบทเรียนนี้ คุณจะมีระบบการต่อสู้ที่สมบูรณ์ซึ่งเลเซอร์สามารถทำลายศัตรูได้ และการชนกันจะกระตุ้นเหตุการณ์ในเกม หลักการตรวจจับการชนกันเหล่านี้ถูกใช้ในทุกอย่างตั้งแต่การจำลองทางฟิสิกส์ไปจนถึงอินเทอร์เฟซเว็บแบบโต้ตอบ
|
|
|
|
✅ ลองค้นคว้าเกี่ยวกับเกมคอมพิวเตอร์เกมแรกที่เคยเขียนขึ้น มันมีฟังก์ชันอะไรบ้าง?
|
|
|
|
## การตรวจจับการชนกัน
|
|
|
|
การตรวจจับการชนกันทำงานเหมือนเซ็นเซอร์ตรวจจับระยะใกล้บนโมดูลดวงจันทร์ของ Apollo - มันจะตรวจสอบระยะห่างอย่างต่อเนื่องและส่งสัญญาณเตือนเมื่อวัตถุเข้าใกล้กันมากเกินไป ในเกม ระบบนี้จะกำหนดว่าเมื่อใดที่วัตถุมีปฏิสัมพันธ์และควรเกิดอะไรขึ้นต่อไป
|
|
|
|
วิธีที่เราจะใช้คือการมองว่าวัตถุในเกมทุกชิ้นเป็นรูปสี่เหลี่ยมผืนผ้า คล้ายกับที่ระบบควบคุมการจราจรทางอากาศใช้รูปทรงเรขาคณิตที่เรียบง่ายเพื่อติดตามเครื่องบิน วิธีการแบบสี่เหลี่ยมนี้อาจดูพื้นฐาน แต่มีประสิทธิภาพในการคำนวณและทำงานได้ดีสำหรับสถานการณ์ในเกมส่วนใหญ่
|
|
|
|
### การแทนค่ารูปสี่เหลี่ยมผืนผ้า
|
|
|
|
วัตถุในเกมทุกชิ้นต้องมีขอบเขตพิกัด คล้ายกับที่รถสำรวจ Mars Pathfinder กำหนดตำแหน่งของมันบนพื้นผิวดาวอังคาร นี่คือวิธีที่เรากำหนดพิกัดขอบเขตเหล่านี้:
|
|
|
|
```javascript
|
|
rectFromGameObject() {
|
|
return {
|
|
top: this.y,
|
|
left: this.x,
|
|
bottom: this.y + this.height,
|
|
right: this.x + this.width
|
|
}
|
|
}
|
|
```
|
|
|
|
**มาดูรายละเอียดกัน:**
|
|
- **ขอบบน**: คือจุดเริ่มต้นในแนวตั้งของวัตถุ (ตำแหน่ง y)
|
|
- **ขอบซ้าย**: คือจุดเริ่มต้นในแนวนอนของวัตถุ (ตำแหน่ง x)
|
|
- **ขอบล่าง**: เพิ่มความสูงเข้าไปในตำแหน่ง y - ตอนนี้คุณรู้แล้วว่ามันสิ้นสุดที่ไหน!
|
|
- **ขอบขวา**: เพิ่มความกว้างเข้าไปในตำแหน่ง x - และคุณได้ขอบเขตทั้งหมดแล้ว
|
|
|
|
### อัลกอริทึมการตัดกัน
|
|
|
|
การตรวจจับการตัดกันของรูปสี่เหลี่ยมผืนผ้าใช้ตรรกะคล้ายกับที่กล้องโทรทรรศน์อวกาศฮับเบิลใช้ในการกำหนดว่าวัตถุท้องฟ้าทับซ้อนกันในมุมมองของมันหรือไม่ อัลกอริทึมจะตรวจสอบการแยก:
|
|
|
|
```javascript
|
|
function intersectRect(r1, r2) {
|
|
return !(r2.left > r1.right ||
|
|
r2.right < r1.left ||
|
|
r2.top > r1.bottom ||
|
|
r2.bottom < r1.top);
|
|
}
|
|
```
|
|
|
|
**การทดสอบการแยกทำงานเหมือนระบบเรดาร์:**
|
|
- รูปสี่เหลี่ยมผืนผ้า 2 อยู่ทางขวาสุดของรูปสี่เหลี่ยมผืนผ้า 1 หรือไม่?
|
|
- รูปสี่เหลี่ยมผืนผ้า 2 อยู่ทางซ้ายสุดของรูปสี่เหลี่ยมผืนผ้า 1 หรือไม่?
|
|
- รูปสี่เหลี่ยมผืนผ้า 2 อยู่ด้านล่างสุดของรูปสี่เหลี่ยมผืนผ้า 1 หรือไม่?
|
|
- รูปสี่เหลี่ยมผืนผ้า 2 อยู่ด้านบนสุดของรูปสี่เหลี่ยมผืนผ้า 1 หรือไม่?
|
|
|
|
หากไม่มีเงื่อนไขเหล่านี้เป็นจริง รูปสี่เหลี่ยมผืนผ้าจะต้องทับซ้อนกัน วิธีนี้คล้ายกับที่ผู้ควบคุมเรดาร์กำหนดว่าเครื่องบินสองลำอยู่ในระยะปลอดภัยหรือไม่
|
|
|
|
## การจัดการวงจรชีวิตของวัตถุ
|
|
|
|
เมื่อเลเซอร์ชนศัตรู วัตถุทั้งสองต้องถูกลบออกจากเกม อย่างไรก็ตาม การลบวัตถุระหว่างลูปอาจทำให้เกิดการล่ม - บทเรียนที่ได้เรียนรู้จากระบบคอมพิวเตอร์ยุคแรก ๆ เช่น Apollo Guidance Computer ดังนั้นเราจึงใช้วิธี "ทำเครื่องหมายเพื่อลบ" ซึ่งจะลบวัตถุอย่างปลอดภัยระหว่างเฟรม
|
|
|
|
นี่คือวิธีที่เราทำเครื่องหมายบางสิ่งเพื่อการลบ:
|
|
|
|
```javascript
|
|
// Mark object for removal
|
|
enemy.dead = true;
|
|
```
|
|
|
|
**ทำไมวิธีนี้ถึงได้ผล:**
|
|
- เราทำเครื่องหมายวัตถุว่า "ตาย" แต่ยังไม่ลบมันทันที
|
|
- สิ่งนี้ช่วยให้เฟรมเกมปัจจุบันเสร็จสิ้นอย่างปลอดภัย
|
|
- ไม่มีการล่มจากการพยายามใช้สิ่งที่ถูกลบไปแล้ว!
|
|
|
|
จากนั้นกรองวัตถุที่ถูกทำเครื่องหมายออกก่อนรอบการแสดงผลครั้งต่อไป:
|
|
|
|
```javascript
|
|
gameObjects = gameObjects.filter(go => !go.dead);
|
|
```
|
|
|
|
**สิ่งที่การกรองนี้ทำ:**
|
|
- สร้างรายการใหม่ที่มีเฉพาะวัตถุที่ "ยังมีชีวิตอยู่"
|
|
- ทิ้งสิ่งที่ถูกทำเครื่องหมายว่าตายไปแล้ว
|
|
- ทำให้เกมของคุณทำงานได้อย่างราบรื่น
|
|
- ป้องกันการสะสมของวัตถุที่ถูกทำลายซึ่งทำให้หน่วยความจำบวม
|
|
|
|
## การนำกลไกเลเซอร์มาใช้
|
|
|
|
โปรเจกไทล์เลเซอร์ในเกมทำงานบนหลักการเดียวกับตอร์ปิโดโฟตอนใน Star Trek - มันเป็นวัตถุที่แยกออกมาและเคลื่อนที่เป็นเส้นตรงจนกว่าจะชนบางสิ่ง การกดแป้นเว้นวรรคแต่ละครั้งจะสร้างวัตถุเลเซอร์ใหม่ที่เคลื่อนที่ข้ามหน้าจอ
|
|
|
|
เพื่อให้สิ่งนี้ทำงาน เราต้องประสานชิ้นส่วนต่าง ๆ:
|
|
|
|
**ส่วนสำคัญที่ต้องนำมาใช้:**
|
|
- **สร้าง** วัตถุเลเซอร์ที่เกิดจากตำแหน่งของฮีโร่
|
|
- **จัดการ** การป้อนข้อมูลจากแป้นพิมพ์เพื่อกระตุ้นการสร้างเลเซอร์
|
|
- **จัดการ** การเคลื่อนที่และวงจรชีวิตของเลเซอร์
|
|
- **นำเสนอ** การแสดงผลภาพสำหรับโปรเจกไทล์เลเซอร์
|
|
|
|
## การควบคุมอัตราการยิง
|
|
|
|
อัตราการยิงที่ไม่จำกัดจะทำให้เครื่องยนต์เกมทำงานหนักเกินไปและทำให้การเล่นเกมง่ายเกินไป ระบบอาวุธจริงก็เผชิญกับข้อจำกัดที่คล้ายกัน - แม้แต่ปืนเฟเซอร์ของ USS Enterprise ก็ต้องใช้เวลาชาร์จระหว่างการยิง
|
|
|
|
เราจะนำระบบคูลดาวน์มาใช้เพื่อป้องกันการยิงแบบรัว ๆ ในขณะที่ยังคงควบคุมได้อย่างตอบสนอง:
|
|
|
|
```javascript
|
|
class Cooldown {
|
|
constructor(time) {
|
|
this.cool = false;
|
|
setTimeout(() => {
|
|
this.cool = true;
|
|
}, time);
|
|
}
|
|
}
|
|
|
|
class Weapon {
|
|
constructor() {
|
|
this.cooldown = null;
|
|
}
|
|
|
|
fire() {
|
|
if (!this.cooldown || this.cooldown.cool) {
|
|
// Create laser projectile
|
|
this.cooldown = new Cooldown(500);
|
|
} else {
|
|
// Weapon is still cooling down
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**วิธีการทำงานของคูลดาวน์:**
|
|
- เมื่อสร้างขึ้น อาวุธจะเริ่มต้นเป็น "ร้อน" (ยังยิงไม่ได้)
|
|
- หลังจากช่วงเวลาที่กำหนด มันจะกลายเป็น "เย็น" (พร้อมยิง)
|
|
- ก่อนยิง เราจะตรวจสอบว่า "อาวุธเย็นหรือยัง?"
|
|
- สิ่งนี้ป้องกันการคลิกแบบรัว ๆ ในขณะที่ยังคงควบคุมได้อย่างตอบสนอง
|
|
|
|
✅ อ้างอิงบทเรียนที่ 1 ในซีรีส์เกมอวกาศเพื่อเตือนตัวเองเกี่ยวกับคูลดาวน์
|
|
|
|
## การสร้างระบบตรวจจับการชนกัน
|
|
|
|
คุณจะขยายโค้ดเกมอวกาศที่มีอยู่ของคุณเพื่อสร้างระบบตรวจจับการชนกัน เช่นเดียวกับระบบหลีกเลี่ยงการชนกันอัตโนมัติของสถานีอวกาศนานาชาติ เกมของคุณจะตรวจสอบตำแหน่งของวัตถุอย่างต่อเนื่องและตอบสนองต่อการตัดกัน
|
|
|
|
เริ่มต้นจากโค้ดบทเรียนก่อนหน้านี้ของคุณ คุณจะเพิ่มการตรวจจับการชนกันพร้อมกฎเฉพาะที่ควบคุมการมีปฏิสัมพันธ์ของวัตถุ
|
|
|
|
> 💡 **เคล็ดลับ**: สไปรต์เลเซอร์มีอยู่แล้วในโฟลเดอร์ทรัพย์สินของคุณและอ้างอิงในโค้ดของคุณ พร้อมสำหรับการนำไปใช้
|
|
|
|
### กฎการชนกันที่ต้องนำมาใช้
|
|
|
|
**กลไกเกมที่ต้องเพิ่ม:**
|
|
1. **เลเซอร์ชนศัตรู**: วัตถุศัตรูจะถูกทำลายเมื่อถูกโปรเจกไทล์เลเซอร์
|
|
2. **เลเซอร์ชนขอบหน้าจอ**: เลเซอร์จะถูกลบเมื่อถึงขอบบนของหน้าจอ
|
|
3. **ศัตรูชนฮีโร่**: วัตถุทั้งสองจะถูกทำลายเมื่อชนกัน
|
|
4. **ศัตรูถึงด้านล่าง**: เงื่อนไขเกมโอเวอร์เมื่อศัตรูถึงด้านล่างของหน้าจอ
|
|
|
|
## การตั้งค่าสภาพแวดล้อมการพัฒนา
|
|
|
|
ข่าวดี - เราได้ตั้งค่าพื้นฐานส่วนใหญ่ให้คุณแล้ว! ทรัพยากรเกมและโครงสร้างพื้นฐานทั้งหมดของคุณรออยู่ในโฟลเดอร์ `your-work` พร้อมสำหรับคุณที่จะเพิ่มฟีเจอร์การชนกันที่เจ๋ง ๆ
|
|
|
|
### โครงสร้างโปรเจกต์
|
|
|
|
```bash
|
|
-| assets
|
|
-| enemyShip.png
|
|
-| player.png
|
|
-| laserRed.png
|
|
-| index.html
|
|
-| app.js
|
|
-| package.json
|
|
```
|
|
|
|
**ทำความเข้าใจโครงสร้างไฟล์:**
|
|
- **มี** ภาพสไปรต์ทั้งหมดที่จำเป็นสำหรับวัตถุในเกม
|
|
- **รวม** เอกสาร HTML หลักและไฟล์แอปพลิเคชัน JavaScript
|
|
- **จัดเตรียม** การกำหนดค่าของแพ็กเกจสำหรับเซิร์ฟเวอร์พัฒนาท้องถิ่น
|
|
|
|
### การเริ่มเซิร์ฟเวอร์พัฒนา
|
|
|
|
ไปที่โฟลเดอร์โปรเจกต์ของคุณและเริ่มเซิร์ฟเวอร์ท้องถิ่น:
|
|
|
|
```bash
|
|
cd your-work
|
|
npm start
|
|
```
|
|
|
|
**ลำดับคำสั่งนี้:**
|
|
- **เปลี่ยน**ไดเรกทอรีไปยังโฟลเดอร์โปรเจกต์ที่คุณทำงานอยู่
|
|
- **เริ่มต้น**เซิร์ฟเวอร์ HTTP ท้องถิ่นที่ `http://localhost:5000`
|
|
- **ให้บริการ**ไฟล์เกมของคุณสำหรับการทดสอบและพัฒนา
|
|
- **เปิดใช้งาน**การพัฒนาแบบสดพร้อมการรีโหลดอัตโนมัติ
|
|
|
|
เปิดเบราว์เซอร์ของคุณและไปที่ `http://localhost:5000` เพื่อดูสถานะเกมปัจจุบันของคุณพร้อมฮีโร่และศัตรูที่แสดงบนหน้าจอ
|
|
|
|
### การนำไปใช้ทีละขั้นตอน
|
|
|
|
เช่นเดียวกับวิธีการที่ NASA ใช้ในการเขียนโปรแกรมยานอวกาศ Voyager เราจะนำการตรวจจับการชนกันมาใช้อย่างเป็นระบบ โดยสร้างแต่ละส่วนทีละขั้นตอน
|
|
|
|
#### 1. เพิ่มขอบเขตการชนกันของรูปสี่เหลี่ยมผืนผ้า
|
|
|
|
ก่อนอื่น มาสอนวัตถุในเกมของเราให้บอกขอบเขตของมันกัน เพิ่มเมธอดนี้ในคลาส `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
|
|
);
|
|
}
|
|
```
|
|
|
|
**อัลกอริทึมนี้ทำงานโดย:**
|
|
- **ทดสอบ**เงื่อนไขการแยกสี่ข้อระหว่างรูปสี่เหลี่ยม
|
|
- **ส่งคืน** `false` หากเงื่อนไขการแยกใด ๆ เป็นจริง
|
|
- **ระบุ**การชนกันเมื่อไม่มีการแยก
|
|
- **ใช้**ตรรกะการปฏิเสธเพื่อการทดสอบการตัดกันที่มีประสิทธิภาพ
|
|
|
|
#### 3. นำระบบการยิงเลเซอร์มาใช้
|
|
|
|
นี่คือจุดที่น่าตื่นเต้น! มาตั้งค่าระบบการยิงเลเซอร์กัน
|
|
|
|
##### ค่าคงที่ข้อความ
|
|
|
|
ก่อนอื่น มากำหนดประเภทข้อความบางประเภทเพื่อให้ส่วนต่าง ๆ ของเกมของเราสามารถสื่อสารกันได้:
|
|
|
|
```javascript
|
|
KEY_EVENT_SPACE: "KEY_EVENT_SPACE",
|
|
COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER",
|
|
COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
|
|
```
|
|
|
|
**ค่าคงที่เหล่านี้ให้:**
|
|
- **มาตรฐาน**ชื่อเหตุการณ์ทั่วทั้งแอปพลิเคชัน
|
|
- **เปิดใช้งาน**การสื่อสารที่สอดคล้องกันระหว่างระบบเกม
|
|
- **ป้องกัน**ข้อผิดพลาดในการพิมพ์ในการลงทะเบียนตัวจัดการเหตุการณ์
|
|
|
|
##### การจัดการการป้อนข้อมูลจากแป้นพิมพ์
|
|
|
|
เพิ่มการตรวจจับแป้นเว้นวรรคในตัวฟังเหตุการณ์แป้นพิมพ์ของคุณ:
|
|
|
|
```javascript
|
|
} else if(evt.keyCode === 32) {
|
|
eventEmitter.emit(Messages.KEY_EVENT_SPACE);
|
|
}
|
|
```
|
|
|
|
**ตัวจัดการการป้อนข้อมูลนี้:**
|
|
- **ตรวจจับ**การกดแป้นเว้นวรรคโดยใช้ keyCode 32
|
|
- **ส่ง**ข้อความเหตุการณ์มาตรฐาน
|
|
- **เปิดใช้งาน**ตรรกะการยิงที่แยกออกจากกัน
|
|
|
|
##### การตั้งค่าตัวฟังเหตุการณ์
|
|
|
|
ลงทะเบียนพฤติกรรมการยิงในฟังก์ชัน `initGame()` ของคุณ:
|
|
|
|
```javascript
|
|
eventEmitter.on(Messages.KEY_EVENT_SPACE, () => {
|
|
if (hero.canFire()) {
|
|
hero.fire();
|
|
}
|
|
});
|
|
```
|
|
|
|
**ตัวฟังเหตุการณ์นี้:**
|
|
- **ตอบสนอง**ต่อเหตุการณ์แป้นเว้นวรรค
|
|
- **ตรวจสอบ**สถานะคูลดาวน์การยิง
|
|
- **กระตุ้น**การสร้างเลเซอร์เมื่อได้รับอนุญาต
|
|
|
|
เพิ่มการจัดการการชนกันสำหรับการโต้ตอบระหว่างเลเซอร์และศัตรู:
|
|
|
|
```javascript
|
|
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
|
|
first.dead = true;
|
|
second.dead = true;
|
|
});
|
|
```
|
|
|
|
**ตัวจัดการการชนกันนี้:**
|
|
- **รับ**ข้อมูลเหตุการณ์การชนกันพร้อมวัตถุทั้งสอง
|
|
- **ทำเครื่องหมาย**วัตถุทั้งสองเพื่อการลบ
|
|
- **รับรอง**การทำความสะอาดที่เหมาะสมหลังการชนกัน
|
|
|
|
#### 4. สร้างคลาส Laser
|
|
|
|
นำโปรเจกไทล์เลเซอร์มาใช้ที่เคลื่อนที่ขึ้นด้านบนและจัดการวงจรชีวิตของมันเอง:
|
|
|
|
```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);
|
|
}
|
|
}
|
|
```
|
|
|
|
**การนำคลาสนี้ไปใช้:**
|
|
- **ขยาย** GameObject เพื่อรับฟังก์ชันพื้นฐาน
|
|
- **ตั้งค่า**ขนาดที่เหมาะสมสำหรับสไปรต์เลเซอร์
|
|
- **สร้าง**การเคลื่อนที่ขึ้นด้านบนโดยอัตโนมัติด้วย `setInterval()`
|
|
- **จัดการ**การทำลายตัวเองเมื่อถึงด้านบนของหน้าจอ
|
|
- **จัดการ**เวลาแอนิเมชันและการทำความสะอาดของตัวเอง
|
|
|
|
#### 5. นำระบบตรวจจับการชนกันมาใช้
|
|
|
|
สร้างฟังก์ชันตรวจจับการชนกันที่ครอบคลุม:
|
|
|
|
```javascript
|
|
function updateGameObjects() {
|
|
const enemies = gameObjects.filter(go => go.type === 'Enemy');
|
|
const lasers = gameObjects.filter(go => go.type === "Laser");
|
|
|
|
// Test laser-enemy collisions
|
|
lasers.forEach((laser) => {
|
|
enemies.forEach((enemy) => {
|
|
if (intersectRect(laser.rectFromGameObject(), enemy.rectFromGameObject())) {
|
|
eventEmitter.emit(Messages.COLLISION_ENEMY_LASER, {
|
|
first: laser,
|
|
second: enemy,
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// Remove destroyed objects
|
|
gameObjects = gameObjects.filter(go => !go.dead);
|
|
}
|
|
```
|
|
|
|
**ระบบการชนกันนี้:**
|
|
- **กรอง**วัตถุในเกมตามประเภทเพื่อการทดสอบที่มีประสิทธิภาพ
|
|
- **ทดสอบ**เลเซอร์ทุกอันกับศัตรูทุกตัวเพื่อการตัดกัน
|
|
- **ส่ง**เหตุการณ์การชนกันเมื่อพบการตัดกัน
|
|
- **ทำความสะอาด**วัตถุที่ถูกทำลายหลังการประมวลผลการชนกัน
|
|
|
|
> ⚠️ **สำคัญ**: เพิ่ม `updateGameObjects()` ในลูปเกมหลักของคุณใน `window.onload` เพื่อเปิดใช้งานการตรวจจับการชนกัน
|
|
|
|
#### 6. เพิ่มระบบคูลดาวน์ในคลาส Hero
|
|
|
|
ปรับปรุงคลาส 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;
|
|
}
|
|
}
|
|
```
|
|
|
|
**ทำความเข้าใจคลาส Hero ที่ปรับปรุงแล้ว:**
|
|
- **เริ่มต้น**ตัวจับเวลาคูลดาวน์ที่ศูนย์ (พร้อมยิง)
|
|
- **สร้าง**วัตถุเลเซอร์ที่วางตำแหน่งเหนือยานฮีโร่
|
|
- **ตั้งค่า**ช่วงเวลาคูลดาวน์เพื่อป้องกันการยิงแบบรัว
|
|
- **ลดลง**ตัวจับเวลาคูลดาวน์โดยใช้การอ
|
|
|
|
---
|
|
|
|
**ข้อจำกัดความรับผิดชอบ**:
|
|
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลโดยอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้ |