|
1 week ago | |
---|---|---|
.. | ||
solution | 1 week ago | |
your-work | 1 week ago | |
README.md | 1 week ago | |
assignment.md | 1 week ago |
README.md
สร้างเกมอวกาศ ตอนที่ 4: เพิ่มเลเซอร์และตรวจจับการชน
แบบทดสอบก่อนเรียน
ในบทเรียนนี้ คุณจะได้เรียนรู้วิธีการยิงเลเซอร์ด้วย JavaScript! เราจะเพิ่มสองสิ่งในเกมของเรา:
- เลเซอร์: เลเซอร์นี้จะถูกยิงจากยานของฮีโร่และพุ่งขึ้นในแนวตั้ง
- การตรวจจับการชน: ในการเพิ่มความสามารถในการ ยิง เราจะเพิ่มกฎของเกมที่น่าสนใจดังนี้:
- เลเซอร์ชนศัตรู: ศัตรูจะตายเมื่อถูกเลเซอร์ยิง
- เลเซอร์ชนขอบบนของหน้าจอ: เลเซอร์จะถูกทำลายเมื่อชนขอบบนของหน้าจอ
- ศัตรูชนฮีโร่: ศัตรูและฮีโร่จะถูกทำลายเมื่อชนกัน
- ศัตรูชนขอบล่างของหน้าจอ: ศัตรูและฮีโร่จะถูกทำลายเมื่อศัตรูชนขอบล่างของหน้าจอ
สรุปคือ คุณ -- ฮีโร่ -- ต้องยิงศัตรูทั้งหมดด้วยเลเซอร์ก่อนที่พวกมันจะเคลื่อนที่ไปถึงขอบล่างของหน้าจอ
✅ ลองค้นคว้าเกี่ยวกับเกมคอมพิวเตอร์เกมแรกที่เคยถูกสร้างขึ้น มันมีฟังก์ชันการทำงานอะไรบ้าง?
มาร่วมเป็นฮีโร่ไปด้วยกัน!
การตรวจจับการชน
เราจะตรวจจับการชนได้อย่างไร? เราต้องคิดว่าออบเจ็กต์ในเกมของเราเป็นสี่เหลี่ยมที่เคลื่อนที่ไปมา ทำไมถึงเป็นแบบนั้น? เพราะภาพที่ใช้ในการวาดออบเจ็กต์ในเกมเป็นรูปสี่เหลี่ยม: มันมี x
, y
, width
และ height
ถ้าสี่เหลี่ยมสองอัน เช่น ฮีโร่และศัตรู ตัดกัน นั่นหมายถึงเกิดการชน สิ่งที่ควรเกิดขึ้นหลังจากนั้นขึ้นอยู่กับกฎของเกม ในการสร้างการตรวจจับการชน คุณจะต้องมีสิ่งต่อไปนี้:
-
วิธีการสร้างตัวแทนสี่เหลี่ยมของออบเจ็กต์ในเกม เช่นนี้:
rectFromGameObject() { return { top: this.y, left: this.x, bottom: this.y + this.height, right: this.x + this.width } }
-
ฟังก์ชันเปรียบเทียบ ฟังก์ชันนี้อาจมีหน้าตาแบบนี้:
function intersectRect(r1, r2) { return !(r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top); }
วิธีการทำลายสิ่งต่าง ๆ
ในการทำลายสิ่งต่าง ๆ ในเกม คุณต้องแจ้งให้เกมทราบว่าไม่ควรวาดออบเจ็กต์นี้อีกในลูปของเกมที่ทำงานในช่วงเวลาที่กำหนด วิธีหนึ่งคือการทำเครื่องหมายว่าออบเจ็กต์ในเกม ตาย เมื่อเกิดเหตุการณ์บางอย่าง เช่นนี้:
// collision happened
enemy.dead = true
จากนั้นคุณสามารถจัดการกับออบเจ็กต์ที่ ตาย ก่อนที่จะวาดหน้าจอใหม่ เช่นนี้:
gameObjects = gameObject.filter(go => !go.dead);
วิธีการยิงเลเซอร์
การยิงเลเซอร์หมายถึงการตอบสนองต่อเหตุการณ์กดปุ่มและสร้างออบเจ็กต์ที่เคลื่อนที่ในทิศทางที่กำหนด ดังนั้นเราต้องทำตามขั้นตอนต่อไปนี้:
- สร้างออบเจ็กต์เลเซอร์: จากด้านบนของยานฮีโร่ ซึ่งเมื่อถูกสร้างขึ้นจะเริ่มเคลื่อนที่ขึ้นไปยังขอบบนของหน้าจอ
- ผูกโค้ดกับเหตุการณ์กดปุ่ม: เราต้องเลือกปุ่มบนคีย์บอร์ดที่แทนการยิงเลเซอร์ของผู้เล่น
- สร้างออบเจ็กต์ในเกมที่ดูเหมือนเลเซอร์ เมื่อปุ่มถูกกด
การหน่วงเวลาในการยิงเลเซอร์
เลเซอร์ต้องถูกยิงทุกครั้งที่คุณกดปุ่ม เช่น space เพื่อป้องกันไม่ให้เกมสร้างเลเซอร์มากเกินไปในช่วงเวลาสั้น ๆ เราต้องแก้ไขสิ่งนี้ วิธีแก้ไขคือการเพิ่มสิ่งที่เรียกว่า cooldown หรือการหน่วงเวลา ซึ่งเป็นตัวจับเวลาที่ทำให้เลเซอร์สามารถยิงได้ในช่วงเวลาที่กำหนดเท่านั้น คุณสามารถทำได้ดังนี้:
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 ในซีรีส์เกมอวกาศเพื่อทบทวนเกี่ยวกับ cooldowns
สิ่งที่ต้องสร้าง
คุณจะนำโค้ดที่มีอยู่ (ซึ่งคุณควรทำความสะอาดและปรับปรุงแล้ว) จากบทเรียนก่อนหน้า และขยายมันต่อไป คุณสามารถเริ่มต้นด้วยโค้ดจากตอนที่ II หรือใช้โค้ดจาก Part III- starter
เคล็ดลับ: เลเซอร์ที่คุณจะทำงานด้วยนั้นอยู่ในโฟลเดอร์ assets ของคุณแล้วและถูกอ้างอิงในโค้ดของคุณ
- เพิ่มการตรวจจับการชน เมื่อเลเซอร์ชนกับบางสิ่ง กฎต่อไปนี้ควรนำมาใช้:
- เลเซอร์ชนศัตรู: ศัตรูจะตายเมื่อถูกเลเซอร์ยิง
- เลเซอร์ชนขอบบนของหน้าจอ: เลเซอร์จะถูกทำลายเมื่อชนขอบบนของหน้าจอ
- ศัตรูชนฮีโร่: ศัตรูและฮีโร่จะถูกทำลายเมื่อชนกัน
- ศัตรูชนขอบล่างของหน้าจอ: ศัตรูและฮีโร่จะถูกทำลายเมื่อศัตรูชนขอบล่างของหน้าจอ
ขั้นตอนที่แนะนำ
ค้นหาไฟล์ที่ถูกสร้างไว้ให้คุณในโฟลเดอร์ your-work
มันควรมีสิ่งต่อไปนี้:
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| index.html
-| app.js
-| package.json
เริ่มโปรเจกต์ของคุณในโฟลเดอร์ your_work
โดยพิมพ์:
cd your-work
npm start
คำสั่งด้านบนจะเริ่ม HTTP Server ที่อยู่ http://localhost:5000
เปิดเบราว์เซอร์และใส่ที่อยู่นั้น ตอนนี้มันควรแสดงฮีโร่และศัตรูทั้งหมด แต่ยังไม่มีอะไรเคลื่อนไหว :)
เพิ่มโค้ด
-
ตั้งค่าตัวแทนสี่เหลี่ยมของออบเจ็กต์ในเกมเพื่อจัดการการชน โค้ดด้านล่างช่วยให้คุณสร้างตัวแทนสี่เหลี่ยมของ
GameObject
แก้ไขคลาส GameObject ของคุณเพื่อขยายมัน:rectFromGameObject() { return { top: this.y, left: this.x, bottom: this.y + this.height, right: this.x + this.width, }; }
-
เพิ่มโค้ดที่ตรวจสอบการชน นี่จะเป็นฟังก์ชันใหม่ที่ทดสอบว่าสี่เหลี่ยมสองอันตัดกันหรือไม่:
function intersectRect(r1, r2) { return !( r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top ); }
-
เพิ่มความสามารถในการยิงเลเซอร์
-
เพิ่มข้อความเหตุการณ์กดปุ่ม ปุ่ม space ควรสร้างเลเซอร์ที่อยู่เหนือยานฮีโร่ เพิ่มค่าคงที่สามตัวในออบเจ็กต์ Messages:
KEY_EVENT_SPACE: "KEY_EVENT_SPACE", COLLISION_ENEMY_LASER: "COLLISION_ENEMY_LASER", COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
-
จัดการปุ่ม space แก้ไขฟังก์ชัน
window.addEventListener
keyup เพื่อจัดการ space:} else if(evt.keyCode === 32) { eventEmitter.emit(Messages.KEY_EVENT_SPACE); }
-
เพิ่มตัวฟังเหตุการณ์ แก้ไขฟังก์ชัน
initGame()
เพื่อให้แน่ใจว่าฮีโร่สามารถยิงได้เมื่อกด space bar:eventEmitter.on(Messages.KEY_EVENT_SPACE, () => { if (hero.canFire()) { hero.fire(); }
และเพิ่มฟังก์ชัน
eventEmitter.on()
ใหม่เพื่อจัดการพฤติกรรมเมื่อศัตรูชนกับเลเซอร์:eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => { first.dead = true; second.dead = true; })
-
เคลื่อนที่ออบเจ็กต์ ตรวจสอบให้แน่ใจว่าเลเซอร์เคลื่อนที่ไปยังขอบบนของหน้าจออย่างค่อยเป็นค่อยไป คุณจะสร้างคลาส Laser ใหม่ที่ขยาย
GameObject
เช่นเดียวกับที่คุณเคยทำมาก่อน: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) } }
-
จัดการการชน นำกฎการชนสำหรับเลเซอร์ไปใช้ เพิ่มฟังก์ชัน
updateGameObjects()
ที่ทดสอบออบเจ็กต์ที่ชนกัน: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
-
เพิ่ม cooldown ให้กับเลเซอร์ เพื่อให้สามารถยิงได้ในช่วงเวลาที่กำหนดเท่านั้น
สุดท้าย แก้ไขคลาส Hero เพื่อให้สามารถหน่วงเวลาได้:
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 bar และศัตรูจะหายไปเมื่อคุณยิงโดนพวกมัน เก่งมาก!
🚀 ความท้าทาย
เพิ่มเอฟเฟกต์ระเบิด! ลองดูที่ทรัพยากรเกมใน Space Art repo และลองเพิ่มเอฟเฟกต์ระเบิดเมื่อเลเซอร์ชนกับเอเลี่ยน
แบบทดสอบหลังเรียน
ทบทวนและศึกษาด้วยตัวเอง
ทดลองปรับช่วงเวลาในเกมของคุณจนถึงตอนนี้ จะเกิดอะไรขึ้นเมื่อคุณเปลี่ยนมัน? อ่านเพิ่มเติมเกี่ยวกับ JavaScript timing events
การบ้าน
ข้อจำกัดความรับผิดชอบ:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI Co-op Translator แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่แม่นยำ เอกสารต้นฉบับในภาษาต้นทางควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามนุษย์มืออาชีพ เราจะไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความที่ผิดพลาดซึ่งเกิดจากการใช้การแปลนี้