|
|
4 months ago | |
|---|---|---|
| .. | ||
| README.md | 4 months ago | |
| assignment.md | 6 months ago | |
README.md
สร้างเกมอวกาศ ตอนที่ 3: การเพิ่มการเคลื่อนที่
journey
title การเดินทางแอนิเมชันเกมของคุณ
section พื้นฐานการเคลื่อนไหว
เข้าใจหลักการเคลื่อนไหว: 3: Student
เรียนรู้การอัปเดตพิกัด: 4: Student
นำการเคลื่อนไหวพื้นฐานไปใช้: 4: Student
section การควบคุมผู้เล่น
จัดการเหตุการณ์แป้นพิมพ์: 4: Student
ป้องกันพฤติกรรมเริ่มต้น: 5: Student
สร้างการควบคุมที่ตอบสนอง: 5: Student
section ระบบเกม
สร้างวงจรเกม: 5: Student
จัดการวงจรชีวิตวัตถุ: 5: Student
นำแนวทาง pub/sub ไปใช้: 5: Student
ลองคิดถึงเกมที่คุณชอบที่สุด – สิ่งที่ทำให้เกมเหล่านั้นน่าติดตามไม่ใช่แค่กราฟิกที่สวยงามเท่านั้น แต่คือวิธีที่ทุกอย่างเคลื่อนไหวและตอบสนองต่อการกระทำของคุณ ตอนนี้เกมอวกาศของคุณเหมือนภาพวาดที่สวยงาม แต่เรากำลังจะเพิ่มการเคลื่อนไหวที่ทำให้มันมีชีวิต
เมื่อวิศวกรของ NASA เขียนโปรแกรมคอมพิวเตอร์สำหรับการนำทางในภารกิจ Apollo พวกเขาต้องเผชิญกับความท้าทายคล้ายกัน: จะทำอย่างไรให้ยานอวกาศตอบสนองต่อการควบคุมของนักบินในขณะเดียวกันก็คงเส้นทางได้โดยอัตโนมัติ หลักการที่เราจะเรียนรู้วันนี้สะท้อนแนวคิดเหล่านั้น – การจัดการการเคลื่อนไหวที่ควบคุมโดยผู้เล่นควบคู่กับพฤติกรรมอัตโนมัติของระบบ
ในบทเรียนนี้ คุณจะได้เรียนรู้วิธีทำให้ยานอวกาศลื่นไหลผ่านหน้าจอ ตอบสนองต่อคำสั่งของผู้เล่น และสร้างรูปแบบการเคลื่อนไหวที่ราบรื่น เราจะแบ่งทุกอย่างออกเป็นแนวคิดที่เข้าใจง่ายและต่อเนื่องกันอย่างเป็นธรรมชาติ
เมื่อจบบทเรียน คุณจะมีผู้เล่นบินเรือฮีโร่ไปรอบหน้าจอ ในขณะที่เรือศัตรูก็ลาดตระเวนอยู่เหนือน่านฟ้า ที่สำคัญกว่านั้น คุณจะเข้าใจหลักการสำคัญที่ขับเคลื่อนระบบการเคลื่อนไหวของเกม
mindmap
root((แอนิเมชันเกม))
Movement Types
Player Controlled [ผู้เล่นควบคุม]
Automatic Motion [การเคลื่อนที่อัตโนมัติ]
Physics Based [อิงฟิสิกส์]
Scripted Paths [เส้นทางกำหนดสคริปต์]
Event Handling
Keyboard Input [ป้อนข้อมูลแป้นพิมพ์]
Mouse Events [เหตุการณ์เมาส์]
Touch Controls [การควบคุมสัมผัส]
Default Prevention [ป้องกันค่าปริยาย]
Game Loop
Update Logic [อัปเดตตรรกะ]
Render Frame [เรนเดอร์เฟรม]
Clear Canvas [ล้างแคนวาส]
Frame Rate Control [ควบคุมอัตราเฟรม]
Object Management
Position Updates [อัปเดตตำแหน่ง]
Collision Detection [ตรวจจับการชน]
Lifecycle Management [จัดการวงจรชีวิต]
State Tracking [ติดตามสถานะ]
Communication
Pub/Sub Pattern [รูปแบบเผยแพร่/สมัครสมาชิก]
Event Emitters [เครื่องปล่อยเหตุการณ์]
Message Passing [ส่งข้อความ]
Loose Coupling [การรวมโค้ดแบบหลวม]
แบบทดสอบก่อนฟังบรรยาย
ทำความเข้าใจการเคลื่อนไหวในเกม
เกมมีชีวิตชีวาเมื่อสิ่งต่างๆ เริ่มเคลื่อนไหว และโดยพื้นฐานมีสองวิธีที่สิ่งเหล่านี้เกิดขึ้น:
- การเคลื่อนไหวที่ควบคุมโดยผู้เล่น: เมื่อคุณกดปุ่มหรือคลิกเมาส์ สิ่งของบางอย่างเคลื่อนที่ นี่คือการเชื่อมโยงโดยตรงระหว่างตัวคุณกับโลกในเกม
- การเคลื่อนไหวอัตโนมัติ: เมื่อเกมตัดสินใจเคลื่อนไหวสิ่งของเอง เช่น เรือศัตรูที่ต้องลาดตระเวนหน้าจอไม่ว่าคุณจะทำอะไรหรือไม่ก็ตาม
การทำให้วัตถุเคลื่อนที่บนหน้าจอคอมพิวเตอร์นั้นง่ายกว่าที่คิด จำพิกัด x และ y จากชั้นเรียนคณิตศาสตร์ได้ไหม? นั่นแหละคือสิ่งที่เรากำลังทำอยู่ เมื่อกาลิเลโอเฝ้าดูดวงจันทร์ของดาวพฤหัสบดีในปี 1610 เขาก็ทำสิ่งเดียวกัน – การกำหนดตำแหน่งตามเวลาเพื่อเข้าใจรูปแบบการเคลื่อนไหว
การเคลื่อนไหวบนหน้าจอเหมือนกับการสร้างภาพเคลื่อนไหวแบบแฟลชบุ๊ก – คุณต้องปฏิบัติตามสามขั้นตอนง่ายๆ เหล่านี้:
flowchart LR
A["เฟรม N"] --> B["อัปเดตตำแหน่ง"]
B --> C["ล้างผืนผ้าใบ"]
C --> D["วาดวัตถุ"]
D --> E["เฟรม N+1"]
E --> F{ต่อไปไหม?}
F -->|ใช่| B
F -->|ไม่| G["เกมจบแล้ว"]
subgraph "วงจรอนิเมชัน"
H["1. คำนวณตำแหน่งใหม่"]
I["2. ลบเฟรมก่อนหน้า"]
J["3. เรนเดอร์เฟรมใหม่"]
end
style B fill:#e1f5fe
style C fill:#ffebee
style D fill:#e8f5e8
- อัปเดตตำแหน่ง – เปลี่ยนตำแหน่งของวัตถุ (เช่น เลื่อนมันไปทางขวา 5 พิกเซล)
- ลบเฟรมเก่า – ล้างหน้าจอเพื่อไม่ให้เห็นเงาหรือรอยที่ไม่ต้องการ
- วาดเฟรมใหม่ – วางวัตถุในตำแหน่งใหม่
ทำเร็วพอ แล้วบูม! คุณจะได้การเคลื่อนไหวที่ราบรื่นและรู้สึกเป็นธรรมชาติต่อผู้เล่น
นี่คือตัวอย่างโค้ด:
// ตั้งตำแหน่งของฮีโร่
hero.x += 5;
// ล้างสี่เหลี่ยมที่เป็นที่อยู่ของฮีโร่
ctx.clearRect(0, 0, canvas.width, canvas.height);
// วาดฉากหลังเกมและฮีโร่ใหม่
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.drawImage(heroImg, hero.x, hero.y);
โค้ดนี้ทำอะไร:
- อัปเดต ค่าพิกัด x ของฮีโร่ให้เพิ่มขึ้น 5 พิกเซลเพื่อเคลื่อนที่ไปทางขวา
- ล้าง พื้นที่ของแคนวาสทั้งหมดเพื่อลบเฟรมก่อนหน้า
- เติม พื้นหลังของแคนวาสด้วยสีดำ
- วาดใหม่ ภาพฮีโร่ในตำแหน่งใหม่
✅ คุณคิดได้ไหมว่าทำไมการวาดภาพฮีโร่ใหม่หลายเฟรมต่อวินาทีอาจส่งผลต่อประสิทธิภาพ? อ่านเพิ่มเติมเกี่ยวกับ ทางเลือกของรูปแบบนี้
การจัดการเหตุการณ์แป้นพิมพ์
นี่คือจุดที่เราต่อเชื่อมข้อมูลการป้อนจากผู้เล่นกับการกระทำในเกม เมื่อใครกดปุ่ม spacebar เพื่อยิงเลเซอร์ หรือกดปุ่มลูกศรเพื่อหลบอะสเทอรอยด์ เกมของคุณต้องตรวจจับและตอบสนองต่อข้อมูลนั้น
เหตุการณ์แป้นพิมพ์เกิดขึ้นในระดับหน้าต่างเบราว์เซอร์ หมายความว่าหน้าต่างเบราว์เซอร์ทั้งหมดจะฟังการกดปุ่มเหล่านั้น คลิกเมาส์ในทางกลับกันสามารถจับกับองค์ประกอบเฉพาะ เช่น ปุ่ม สำหรับเกมอวกาศของเรา เราจะโฟกัสที่การควบคุมด้วยแป้นพิมพ์เพราะนี่คือสิ่งที่ให้ความรู้สึกคลาสสิกแบบเกมอาร์เคด
สิ่งนี้ทำให้นึกถึงโอเปอเรเตอร์ระบบโทรเลขในช่วงปี 1800 ที่ต้องแปลงสัญญาณมอร์สให้กลายเป็นข้อความที่มีความหมาย – เราก็กำลังทำสิ่งเดียวกันคือแปลงการกดปุ่มเป็นคำสั่งเกม
ในการจัดการเหตุการณ์ คุณต้องใช้เมธอด addEventListener() ของวินโดวส์ พร้อมกับส่งพารามิเตอร์สองตัว ตัวแรกคือชื่อเหตุการณ์ เช่น keyup ตัวที่สองคือฟังก์ชันที่จะถูกเรียกใช้เมื่อเกิดเหตุการณ์
ตัวอย่างโค้ด:
window.addEventListener('keyup', (evt) => {
// evt.key = การแทนค่ารูปแบบสตริงของปุ่ม
if (evt.key === 'ArrowUp') {
// ทำบางอย่าง
}
});
สรุปสิ่งที่เกิดขึ้น:
- ฟัง เหตุการณ์แป้นพิมพ์บนหน้าต่างทั้งหมด
- รับ อ็อบเจกต์เหตุการณ์ซึ่งมีข้อมูลว่าปุ่มไหนถูกกด
- ตรวจสอบ ว่าปุ่มที่กดตรงกับปุ่มที่กำหนดหรือไม่ (กรณีนี้คือปุ่มลูกศรขึ้น)
- ดำเนินการ โค้ดเมื่อเงื่อนไขเป็นจริง
สำหรับเหตุการณ์คีย์ มีสองคุณสมบัติในเหตุการณ์ที่คุณใช้ดูว่ากดปุ่มไหน:
key- เป็นสตริงแสดงปุ่มที่กด เช่น'ArrowUp'keyCode- เป็นตัวเลขแสดงรหัส เช่น37ซึ่งหมายถึงArrowLeft
✅ การจัดการเหตุการณ์คีย์มีประโยชน์นอกพัฒนาเกม คุณคิดว่าจะใช้เทคนิคนี้ทำอะไรได้อีกบ้าง?
sequenceDiagram
participant User
participant Browser
participant EventSystem
participant GameLogic
participant Hero
User->>Browser: กดปุ่มลูกศรขึ้น
Browser->>EventSystem: เหตุการณ์กดแป้นพิมพ์
EventSystem->>EventSystem: preventDefault()
EventSystem->>GameLogic: emit('KEY_EVENT_UP')
GameLogic->>Hero: hero.y -= 5
Hero->>Hero: อัปเดตตำแหน่ง
Note over Browser,GameLogic: การไหลของเหตุการณ์ป้องกันค่าเริ่มต้นของเบราว์เซอร์
Note over GameLogic,Hero: รูปแบบ pub/sub ช่วยให้การสื่อสารมีความชัดเจน
คีย์พิเศษ: แจ้งเตือน!
ปุ่มบางปุ่มมีพฤติกรรมในตัวของเบราว์เซอร์ที่อาจทำให้เกมของคุณมีปัญหา ปุ่มลูกศรเลื่อนหน้าเว็บ และ spacebar กระโดดลงด้านล่าง – พฤติกรรมที่คุณไม่ต้องการเวลาคนพยายามควบคุมยานอวกาศของพวกเขา
เราสามารถป้องกันพฤติกรรมเริ่มต้นเหล่านี้และปล่อยให้เกมเราเป็นคนจัดการแทน เหมือนกับที่โปรแกรมเมอร์คอมพิวเตอร์ยุคแรกต้องเขียนทับการหยุดชะงักของระบบเพื่อสร้างพฤติกรรมพิเศษ – เรากำลังทำแบบเดียวกันแต่ในระดับเบราว์เซอร์ นี่คือวิธี:
const onKeyDown = function (e) {
console.log(e.keyCode);
switch (e.keyCode) {
case 37:
case 39:
case 38:
case 40: // ปุ่มลูกศร
case 32:
e.preventDefault();
break; // ช่องว่าง
default:
break; // ไม่บล็อกปุ่มอื่น ๆ
}
};
window.addEventListener('keydown', onKeyDown);
เข้าใจโค้ดป้องกันนี้:
- ตรวจสอบ รหัสคีย์ที่อาจทำให้เกิดพฤติกรรมไม่พึงประสงค์
- ป้องกัน พฤติกรรมเบราว์เซอร์เริ่มต้นสำหรับปุ่มลูกศรและ spacebar
- อนุญาต ให้ปุ่มอื่นทำงานได้ตามปกติ
- ใช้
e.preventDefault()เพื่อหยุดพฤติกรรมเริ่มต้นของเบราว์เซอร์
🔄 ตรวจสอบความเข้าใจเชิงการสอน
ความเข้าใจเกี่ยวกับการจัดการเหตุการณ์: ก่อนย้ายไปที่การเคลื่อนไหวอัตโนมัติ ให้แน่ใจว่าคุณสามารถ:
- ✅ อธิบายความแตกต่างระหว่างเหตุการณ์
keydownและkeyup - ✅ เข้าใจเหตุผลที่เราต้องป้องกันพฤติกรรมเริ่มต้นของเบราว์เซอร์
- ✅ อธิบายได้ว่าการฟังเหตุการณ์เชื่อมต่อกับข้อมูลป้อนของผู้ใช้อย่างไร
- ✅ ระบุได้ว่าปุ่มไหนอาจรบกวนการควบคุมเกม
ทดสอบตัวเองแบบด่วน: จะเกิดอะไรขึ้นถ้าคุณไม่ป้องกันพฤติกรรมเริ่มต้นของปุ่มลูกศร? คำตอบ: เบราว์เซอร์จะเลื่อนหน้าเว็บ ทำให้การเคลื่อนไหวในเกมเกิดการรบกวน
สถาปัตยกรรมระบบเหตุการณ์: ตอนนี้คุณเข้าใจว่า:
- การฟังในระดับหน้าต่าง: รับเหตุการณ์ในระดับเบราว์เซอร์
- คุณสมบัติของอ็อบเจกต์เหตุการณ์: สตริง
keyกับตัวเลขkeyCode - การป้องกันพฤติกรรมเริ่มต้น: หยุดพฤติกรรมที่ไม่ต้องการของเบราว์เซอร์
- ตรรกะเงื่อนไข: ตอบสนองต่อชุดปุ่มเฉพาะ
การเคลื่อนไหวที่เกิดจากเกม
ตอนนี้มาคุยถึงวัตถุที่เคลื่อนไหวโดยไม่มีการป้อนข้อมูลจากผู้เล่น ลองนึกถึงเรือศัตรูที่แล่นผ่านหน้าจอ กระสุนที่ยิงเป็นเส้นตรง หรือเมฆที่ลอยอยู่เบื้องหลัง การเคลื่อนไหวอิสระนี้ทำให้โลกในเกมของคุณดูมีชีวิตแม้ไม่มีใครสัมผัสการควบคุมเลย
เราจะใช้ตัวจับเวลาที่มีอยู่ใน JavaScript เพื่ออัปเดตตำแหน่งเป็นช่วงๆ แนวคิดนี้คล้ายกับนาฬิกาลูกตุ้ม – กลไกที่เรียบง่ายที่ทำงานเป็นระยะเวลาสม่ำเสมอ นี่คือตัวอย่างที่ง่าย:
const id = setInterval(() => {
// เคลื่อนศัตรูในแนวแกน y
enemy.y += 10;
}, 100);
โค้ดเคลื่อนไหวนี้ทำอะไร:
- สร้าง ตัวจับเวลาที่ทำงานทุก 100 มิลลิวินาที
- อัปเดต ค่าพิกัด y ของศัตรูเพิ่มขึ้น 10 พิกเซลทุกครั้ง
- เก็บ รหัสตัวจับเวลาไว้เพื่อหยุดเมื่อจำเป็น
- เคลื่อนที่ ศัตรูลงล่างบนหน้าจอโดยอัตโนมัติ
วงจรเกม (Game Loop)
นี่คือแนวคิดที่เชื่อมทุกอย่างเข้าด้วยกัน – วงจรเกม ถ้าเกมของคุณเป็นภาพยนตร์ วงจรเกมคือเครื่องฉายภาพยนตร์ที่แสดงภาพทีละเฟรมอย่างรวดเร็วจนทุกอย่างดูเคลื่อนไหวอย่างราบรื่น
ทุกเกมมีวงจรแบบนี้ทำงานอยู่เบื้องหลัง มันเป็นฟังก์ชันที่อัปเดตวัตถุในเกมทั้งหมด วาดหน้าจอใหม่ และทำซ้ำกระบวนการนี้ตลอดเวลา เพื่อให้ติดตามฮีโร่ ศัตรู และเลเซอร์ต่างๆ ได้ทั้งหมด – สถานะของเกมโดยรวม
แนวคิดนี้ทำให้นึกถึงคนทำแอนิเมชันยุคแรกอย่าง Walt Disney ที่ต้องวาดตัวละครทีละเฟรมเพื่อสร้างภาพเคลื่อนไหว ความจริงแล้วเราแค่ใช้โค้ดแทนดินสอเท่านั้น
นี่คือตัวอย่างโค้ตเกมลูปที่ใช้บ่อย:
flowchart TD
A["เริ่มลูปเกม"] --> B["ล้างผืนผ้าใบ"]
B --> C["เติมพื้นหลัง"]
C --> D["อัปเดตอ็อบเจ็กต์เกม"]
D --> E["วาดฮีโร่"]
E --> F["วาดศัตรู"]
F --> G["วาดองค์ประกอบ UI"]
G --> H["รอสำหรับเฟรมถัดไป"]
H --> I{เกมกำลังทำงานอยู่หรือไม่?}
I -->|ใช่| B
I -->|ไม่ใช่| J["จบเกม"]
subgraph "ควบคุมอัตราเฟรม"
K["60 FPS = 16.67ms"]
L["30 FPS = 33.33ms"]
M["10 FPS = 100ms"]
end
style B fill:#ffebee
style D fill:#e1f5fe
style E fill:#e8f5e8
style F fill:#e8f5e8
const gameLoopId = setInterval(() => {
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawHero();
drawEnemies();
drawStaticObjects();
}
gameLoop();
}, 200);
เข้าใจโครงสร้างเกมลูป:
- ล้าง แคนวาสทั้งหมดเพื่อลบเฟรมก่อนหน้า
- เติม พื้นหลังด้วยสีทึบ
- วาด วัตถุทั้งหมดบนตำแหน่งปัจจุบัน
- ทำซ้ำ ทุก 200 มิลลิวินาทีเพื่อสร้างการเคลื่อนไหวที่ราบรื่น
- จัดการ อัตราเฟรมโดยควบคุมเวลาช่วง
ต่อเนื่องกับเกมอวกาศ
ตอนนี้เราจะเพิ่มการเคลื่อนไหวให้กับฉากนิ่งที่คุณสร้างไว้ก่อนหน้า เราจะเปลี่ยนมันจากภาพนิ่งให้กลายเป็นประสบการณ์โต้ตอบได้ เราจะเดินทีละขั้นตอนเพื่อให้แต่ละชิ้นต่อเนื่องกับส่วนก่อนหน้า
ให้โหลดโค้ดที่เราเลิกไว้จากบทเรียนก่อนหน้า (หรือเริ่มใหม่จากโค้ดในโฟลเดอร์ Part II- starter หากต้องการเริ่มใหม่)
นี่คือสิ่งที่เราจะสร้างวันนี้:
- การควบคุมฮีโร่: ปุ่มลูกศรจะควบคุมยานอวกาศของคุณบนหน้าจอ
- การเคลื่อนไหวศัตรู: เรือเอเลี่ยนเหล่านั้นจะเริ่มเดินหน้า
มาเริ่มลงมือเพิ่มฟีเจอร์เหล่านี้กัน
ขั้นตอนแนะนำ
ค้นหาไฟล์ที่ถูกสร้างให้คุณในโฟลเดอร์ย่อย your-work ซึ่งควรมีดังนี้:
-| assets
-| enemyShip.png
-| player.png
-| index.html
-| app.js
-| package.json
เริ่มโปรเจกต์ในโฟลเดอร์ your-work ด้วยคำสั่ง:
cd your-work
npm start
คำสั่งนี้ทำอะไร:
- เปลี่ยน ไปที่ไดเรกทอรีโปรเจกต์ของคุณ
- เริ่ม เซิร์ฟเวอร์ HTTP ที่อยู่
http://localhost:5000 - ให้บริการ ไฟล์เกมของคุณเพื่อทดสอบในเบราว์เซอร์
คำสั่งข้างต้นจะเริ่มเซิร์ฟเวอร์ HTTP ที่อยู่ http://localhost:5000 เปิดเบราว์เซอร์และใส่ URL นี้ ตอนนี้ควรแสดงฮีโร่และศัตรูทั้งหมด แต่ยังไม่มีการเคลื่อนไหว!
เพิ่มโค้ด
-
เพิ่มวัตถุเฉพาะ สำหรับ
heroและenemyและgame objectแต่ละอันควรมีคุณสมบัติxและy(จำหัวข้อ สืบทอดหรือประกอบ ไว้ด้วย)เคล็ดลับ
game objectควรเป็นตัวเดียวที่มีxและyและสามารถวาดตัวเองบนแคนวาสได้คำแนะนำ: เริ่มด้วยการเพิ่มคลาส
GameObjectใหม่ พร้อมตัวสร้างที่กำหนดไว้ดังนี้ จากนั้นวาดมันลงบนแคนวาส:class GameObject { constructor(x, y) { this.x = x; this.y = y; this.dead = false; this.type = ""; this.width = 0; this.height = 0; this.img = undefined; } draw(ctx) { ctx.drawImage(this.img, this.x, this.y, this.width, this.height); } }เข้าใจคลาสฐานนี้:
- กำหนด คุณสมบัติทั่วไปที่วัตถุเกมทั้งหมดใช้ร่วมกัน (ตำแหน่ง, ขนาด, รูปภาพ)
- รวม ธง
deadเพื่อติดตามว่าวัตถุควรถูกลบหรือไม่ - ให้ เมธอด
draw()เพื่อวาดวัตถุลงบนแคนวาส - ตั้งค่า ค่าเริ่มต้นสำหรับคุณสมบัติทั้งหมดที่คลาสลูกสามารถเขียนทับได้
classDiagram
class GameObject {
+x: number
+y: number
+dead: boolean
+type: string
+width: number
+height: number
+img: Image
+draw(ctx)
}
class Hero {
+speed: number
+type: "ฮีโร่"
+width: 98
+height: 75
}
class Enemy {
+type: "ศัตรู"
+width: 98
+height: 50
+setInterval()
}
GameObject <|-- Hero
GameObject <|-- Enemy
class EventEmitter {
+listeners: object
+on(ข้อความ, ผู้ฟัง)
+emit(ข้อความ, ข้อมูล)
}
ตอนนี้ ขยายคลาส `GameObject` เพื่อสร้าง `Hero` และ `Enemy`:
```javascript
class Hero extends GameObject {
constructor(x, y) {
super(x, y);
this.width = 98;
this.height = 75;
this.type = "Hero";
this.speed = 5;
}
}
```
```javascript
class Enemy extends GameObject {
constructor(x, y) {
super(x, y);
this.width = 98;
this.height = 50;
this.type = "Enemy";
const id = setInterval(() => {
if (this.y < canvas.height - this.height) {
this.y += 5;
} else {
console.log('Stopped at', this.y);
clearInterval(id);
}
}, 300);
}
}
```
**ความคิดสำคัญในคลาสเหล่านี้:**
- **สืบทอด** จาก `GameObject` ด้วยคีย์เวิร์ด `extends`
- **เรียก** ตัวสร้างของตัวแม่ด้วย `super(x, y)`
- **กำหนด** ขนาดและคุณสมบัติเฉพาะสำหรับแต่ละประเภทวัตถุ
- **ดำเนินการ** การเคลื่อนไหวอัตโนมัติสำหรับศัตรูโดยใช้ `setInterval()`
-
เพิ่มตัวจัดการเหตุการณ์คีย์ เพื่อควบคุมการนำทาง (เคลื่อนฮีโร่ขึ้น/ลง ซ้าย/ขวา)
จำไว้ ว่านี่คือระบบพิกัดคาร์ทีเซียน โดยตำแหน่งมุมบนซ้ายคือ
0,0อย่าลืมเพิ่มโค้ดหยุด พฤติกรรมเริ่มต้นคำแนะนำ: สร้างฟังก์ชัน
onKeyDownและแนบเข้ากับวินโดวส์:const onKeyDown = function (e) { console.log(e.keyCode); // เพิ่มโค้ดจากบทเรียนข้างต้นเพื่อหยุดพฤติกรรมเริ่มต้น switch (e.keyCode) { case 37: case 39: case 38: case 40: // ปุ่มลูกศร case 32: e.preventDefault(); break; // ช่องว่าง default: break; // อย่าบล็อกปุ่มอื่น ๆ } }; window.addEventListener("keydown", onKeyDown);ตัวจัดการเหตุการณ์นี้ทำอะไร:
- ฟัง เหตุการณ์ keydown บนหน้าต่างทั้งหมด
- บันทึก รหัสปุ่มเพื่อช่วยดีบักว่าปุ่มไหนถูกกด
- ป้องกัน พฤติกรรมเริ่มต้นของเบราว์เซอร์สำหรับลูกศรและ spacebar
- ปล่อย ให้ปุ่มอื่นทำงานตามปกติ
ตรวจสอบคอนโซลเบราว์เซอร์ตอนนี้และดูการพิมพ์ปุ่มที่ถูกกด
-
ดำเนินการ รูปแบบ Pub sub เพื่อให้โค้ดสะอาดตามส่วนที่เหลือ
รูปแบบ Publish-Subscribe ช่วยจัดระเบียบโค้ดโดยแยกการตรวจจับเหตุการณ์ออกจากการจัดการเหตุการณ์ ทำให้โค้ดแยกส่วนง่ายและดูแลรักษาง่าย
ทำส่วนสุดท้ายนี้โดย:
-
เพิ่มตัวฟังเหตุการณ์ บนวินโดวส์:
window.addEventListener("keyup", (evt) => { if (evt.key === "ArrowUp") { eventEmitter.emit(Messages.KEY_EVENT_UP); } else if (evt.key === "ArrowDown") { eventEmitter.emit(Messages.KEY_EVENT_DOWN); } else if (evt.key === "ArrowLeft") { eventEmitter.emit(Messages.KEY_EVENT_LEFT); } else if (evt.key === "ArrowRight") { eventEmitter.emit(Messages.KEY_EVENT_RIGHT); } });
ระบบเหตุการณ์นี้ทำอะไร:
- ตรวจจับ ข้อมูลแป้นพิมพ์และแปลงเป็นเหตุการณ์เกมส่วนตัว
- แยก การตรวจจับข้อมูลกับตรรกะของเกมออกจากกัน
- ทำให้ เปลี่ยนการควบคุมในภายหลังได้ง่ายโดยไม่กระทบโค้ดเกม
- อนุญาต ระบบหลายตัวตอบสนองข้อมูลเดียวกันได้
-
flowchart TD
A["การป้อนข้อมูลจากแป้นพิมพ์"] --> B["ตัวฟังเหตุการณ์หน้าต่าง"]
B --> C["ตัวปล่อยเหตุการณ์"]
C --> D["เหตุการณ์กดปุ่มขึ้น"]
C --> E["เหตุการณ์กดปุ่มลง"]
C --> F["เหตุการณ์กดปุ่มซ้าย"]
C --> G["เหตุการณ์กดปุ่มขวา"]
D --> H["การเคลื่อนที่ของฮีโร่"]
D --> I["ระบบเสียง"]
D --> J["เอฟเฟกต์ภาพ"]
E --> H
F --> H
G --> H
style A fill:#e1f5fe
style C fill:#e8f5e8
style H fill:#fff3e0
-
สร้างคลาส EventEmitter เพื่อเผยแพร่และสมัครรับข้อความ:
class EventEmitter { constructor() { this.listeners = {}; } on(message, listener) { if (!this.listeners[message]) { this.listeners[message] = []; } this.listeners[message].push(listener); } -
เพิ่มคอนสแตนต์ และตั้งค่า EventEmitter:
const Messages = { KEY_EVENT_UP: "KEY_EVENT_UP", KEY_EVENT_DOWN: "KEY_EVENT_DOWN", KEY_EVENT_LEFT: "KEY_EVENT_LEFT", KEY_EVENT_RIGHT: "KEY_EVENT_RIGHT", }; let heroImg, enemyImg, laserImg, canvas, ctx, gameObjects = [], hero, eventEmitter = new EventEmitter();
เข้าใจการตั้งค่า:
- กำหนด ค่าคงที่ของข้อความเพื่อหลีกเลี่ยงการพิมพ์ผิดและง่ายต่อการแก้ไขโค้ด
- ประกาศ ตัวแปรสำหรับภาพ แคนวาส และสถานะเกม
- สร้าง อีเวนต์อีมิตเตอร์แบบทั่วโลกสำหรับระบบ pub-sub
- กำหนดค่าเริ่มต้น อาร์เรย์เพื่อเก็บวัตถุในเกมทั้งหมด
-
เริ่มต้นเกม
function initGame() { gameObjects = []; createEnemies(); createHero(); eventEmitter.on(Messages.KEY_EVENT_UP, () => { hero.y -= 5; }); eventEmitter.on(Messages.KEY_EVENT_DOWN, () => { hero.y += 5; }); eventEmitter.on(Messages.KEY_EVENT_LEFT, () => { hero.x -= 5; }); -
ตั้งค่าลูปเกม
ปรับโค้ดฟังก์ชัน
window.onloadให้เริ่มต้นเกมและตั้งค่าลูปเกมในช่วงเวลาที่เหมาะสม คุณจะเพิ่มลำแสงเลเซอร์ด้วย:window.onload = async () => { canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); heroImg = await loadTexture("assets/player.png"); enemyImg = await loadTexture("assets/enemyShip.png"); laserImg = await loadTexture("assets/laserRed.png"); initGame(); const gameLoopId = setInterval(() => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); drawGameObjects(ctx); }, 100); };ทำความเข้าใจการตั้งค่าเกม:
- รอ ให้หน้าเว็บโหลดเสร็จสมบูรณ์ก่อนเริ่ม
- รับ อิลิเมนต์แคนวาสและคอนเท็กซ์ 2D ของมัน
- โหลด ไฟล์รูปภาพทั้งหมดแบบไม่ประสานโดยใช้
await - เริ่ม ลูปเกมทำงานที่ช่วงเวลา 100 มิลลิวินาที (10 เฟรมต่อวินาที)
- ล้าง และวาดใหม่ทั้งหน้าจอในแต่ละเฟรม
-
เพิ่มโค้ด เพื่อให้ศัตรูเคลื่อนที่ในช่วงเวลาที่กำหนด
ปรับโค้ดฟังก์ชัน
createEnemies()เพื่อสร้างศัตรูและเพิ่มพวกมันเข้าในคลาส gameObjects ใหม่:function createEnemies() { const MONSTER_TOTAL = 5; const MONSTER_WIDTH = MONSTER_TOTAL * 98; const START_X = (canvas.width - MONSTER_WIDTH) / 2; const STOP_X = START_X + MONSTER_WIDTH; for (let x = START_X; x < STOP_X; x += 98) { for (let y = 0; y < 50 * 5; y += 50) { const enemy = new Enemy(x, y); enemy.img = enemyImg; gameObjects.push(enemy); } } }สิ่งที่การสร้างศัตรูทำ:
- คำนวณ ตำแหน่งเพื่อวางศัตรูให้อยู่กึ่งกลางหน้าจอ
- สร้าง ตารางศัตรูโดยใช้ลูปซ้อนกัน
- กำหนด รูปภาพศัตรูให้แก่แต่ละวัตถุศัตรู
- เพิ่ม ศัตรูแต่ละตัวเข้าอาร์เรย์วัตถุเกมรวม
และเพิ่มฟังก์ชัน
createHero()เพื่อดำเนินการคล้ายกับฮีโร่function createHero() { hero = new Hero( canvas.width / 2 - 45, canvas.height - canvas.height / 4 ); hero.img = heroImg; gameObjects.push(hero); }สิ่งที่การสร้างฮีโร่ทำ:
- วางตำแหน่ง ฮีโร่ที่กึ่งกลางล่างของหน้าจอ
- กำหนด รูปภาพฮีโร่ให้กับวัตถุฮีโร่
- เพิ่ม ฮีโร่เข้าอาร์เรย์วัตถุเกมเพื่อให้สามารถวาดได้
และสุดท้าย เพิ่มฟังก์ชัน
drawGameObjects()เพื่อเริ่มต้นการวาด:function drawGameObjects(ctx) { gameObjects.forEach(go => go.draw(ctx)); }ทำความเข้าใจฟังก์ชันวาด:
- วนลูป ผ่านวัตถุเกมทั้งหมดในอาร์เรย์
- เรียก เมธอด
draw()ในแต่ละวัตถุ - ส่งผ่าน คอนเท็กซ์ของแคนวาสเพื่อให้วัตถุวาดตัวเองได้
🔄 ตรวจสอบความเข้าใจเชิงการสอน
ความเข้าใจระบบเกมครบถ้วน: ตรวจสอบความชำนาญของคุณในสถาปัตยกรรมทั้งหมด:
- ✅ การสืบทอดทำให้ Hero และ Enemy แชร์คุณสมบัติของ GameObject ได้อย่างไร?
- ✅ ทำไมรูปแบบ pub/sub ถึงทำให้โค้ดของคุณดูแลรักษาง่ายขึ้น?
- ✅ ลูปเกมมีบทบาทอย่างไรในการสร้างอนิเมชันที่ลื่นไหล?
- ✅ ตัวฟังเหตุการณ์เชื่อมโยงการป้อนข้อมูลของผู้ใช้เข้ากับพฤติกรรมของวัตถุเกมอย่างไร?
การบูรณาการระบบ: เกมของคุณตอนนี้แสดงให้เห็น:
- การออกแบบเชิงวัตถุ: คลาสแม่พร้อมการสืบทอดเฉพาะทาง
- สถาปัตยกรรมขับเคลื่อนด้วยเหตุการณ์: รูปแบบ pub/sub เพื่อความยืดหยุ่น
- กรอบอนิเมชัน: ลูปเกมกับการอัปเดตเฟรมที่สม่ำเสมอ
- ระบบป้อนข้อมูล: กิจกรรมแป้นพิมพ์พร้อมการป้องกันค่าดีฟอลต์
- การจัดการทรัพยากร: การโหลดภาพและการแสดงสไปรต์
รูปแบบมืออาชีพ: คุณได้ดำเนินการ:
- แยกหน้าที่อย่างชัดเจน: แยกอินพุต, โลจิก และการวาดออกจากกัน
- พอลิมอร์ฟิซึม: ทุกวัตถุเกมแชร์อินเทอร์เฟซการวาดเดียวกัน
- การส่งผ่านข้อความ: การสื่อสารที่สะอาดระหว่างองค์ประกอบต่างๆ
- การจัดการทรัพยากร: การจัดการสไปรต์และอนิเมชันอย่างมีประสิทธิภาพ
ศัตรูของคุณควรเริ่มต้นเคลื่อนที่เข้าหายานอวกาศของฮีโร่แล้ว! } }
and add a `createHero()` function to do a similar process for the hero. ```javascript function createHero() { hero = new Hero( canvas.width / 2 - 45, canvas.height - canvas.height / 4 ); hero.img = heroImg; gameObjects.push(hero); }และสุดท้าย เพิ่มฟังก์ชัน
drawGameObjects()เพื่อเริ่มต้นการวาด:function drawGameObjects(ctx) { gameObjects.forEach(go => go.draw(ctx)); }ศัตรูของคุณควรเริ่มต้นเคลื่อนที่เข้าหายานอวกาศของฮีโร่แล้ว!
ความท้าทาย GitHub Copilot Agent 🚀
นี่คือความท้าทายที่จะช่วยปรับแต่งเกมของคุณ: การเพิ่มขอบเขตและการควบคุมที่ลื่นไหล ขณะนี้ ฮีโร่ของคุณสามารถบินออกนอกหน้าจอได้ และการเคลื่อนไหวอาจรู้สึกกระตุก
ภารกิจของคุณ: ทำให้ยานอวกาศของคุณรู้สึกสมจริงมากขึ้นด้วยการเพิ่มขอบเขตจอและการเคลื่อนไหวที่ลื่นไหล เหมือนกับระบบการควบคุมการบินของ NASA ที่ป้องกันไม่ให้ยานเกินพารามิเตอร์การทำงานที่ปลอดภัย
สิ่งที่ต้องสร้าง: สร้างระบบที่รักษายานอวกาศฮีโร่ให้คงอยู่ในหน้าจอ และทำให้การควบคุมรู้สึกลื่นไหล เมื่อผู้เล่นกดปุ่มลูกศรค้างไว้ ยานควรเคลื่อนต่อเนื่องแทนการเคลื่อนเป็นขั้นๆ ลองเพิ่มสัญญาณภาพเมื่อยานถึงขอบหน้าจอ – เช่น เอฟเฟกต์เบาๆ เพื่อบอกขอบเขตพื้นที่เล่น
เรียนรู้เพิ่มเติมเกี่ยวกับ โหมด agent ที่นี่
🚀 ความท้าทาย
การจัดระเบียบโค้ดสำคัญขึ้นเรื่อยๆ เมื่อโปรเจกต์โตขึ้น คุณอาจสังเกตเห็นไฟล์ของคุณแน่นไปด้วยฟังก์ชัน, ตัวแปร และคลาสที่ผสมกัน นี่เตือนฉันถึงวิธีที่วิศวกรโค้ดของภารกิจ Apollo ต้องสร้างระบบที่ชัดเจนและดูแลรักษาง่ายซึ่งทีมหลายทีมสามารถทำงานพร้อมกันได้
ภารกิจของคุณ: คิดเหมือนสถาปนิกซอฟต์แวร์ คุณจะจัดระเบียบโค้ดอย่างไรเพื่อให้หลังจากหกเดือน คุณ (หรือเพื่อนร่วมงาน) สามารถเข้าใจสิ่งที่เกิดขึ้น แม้ตอนนี้ทุกอย่างจะยังอยู่ในไฟล์เดียว คุณก็ยังสามารถจัดระเบียบได้ดีขึ้นโดย:
- จัดกลุ่มฟังก์ชันที่เกี่ยวข้อง ด้วยหัวข้อคอมเมนต์ที่ชัดเจน
- แยกหน้าที่กัน - แยกโลจิกเกมออกจากการวาด
- ใช้การตั้งชื่อตัวแปรและฟังก์ชันที่สม่ำเสมอ
- สร้างโมดูล หรือเนมสเปซเพื่อจัดการส่วนต่างๆ ของเกม
- เพิ่มเอกสาร อธิบายจุดประสงค์ของแต่ละส่วนหลัก
คำถามสะท้อนความคิด:
- ส่วนใดของโค้ดที่คุณเข้าใจยากที่สุดเวลาคุณกลับมาดูอีกครั้ง?
- คุณจะจัดระเบียบโค้ดยังไงเพื่อให้ง่ายต่อการมีส่วนร่วมของผู้อื่น?
- จะเกิดอะไรขึ้นถ้าคุณต้องการเพิ่มฟีเจอร์ใหม่ๆ เช่น power-ups หรือศัตรูประเภทใหม่?
แบบทดสอบหลังเรียน
รีวิว & เรียนรู้ด้วยตนเอง
เราสร้างทุกอย่างตั้งแต่เริ่มต้น ซึ่งดีมากสำหรับการเรียนรู้ แต่มีความลับอยู่ – มีเฟรมเวิร์ก JavaScript ที่ยอดเยี่ยมหลายตัวที่ช่วยจัดการงานหนักให้คุณได้ เมื่อคุณชำนาญพื้นฐานที่เราเรียนไปแล้ว ก็คุ้มค่าที่จะ สำรวจสิ่งที่มีอยู่
คิดว่าเฟรมเวิร์กเหมือนกล่องเครื่องมือที่เต็มไปด้วยเครื่องมือ แทนที่จะทำเครื่องมือทุกชิ้นด้วยมือเอง พวกมันช่วยแก้ปัญหาการจัดระเบียบโค้ดที่เราพูดถึง รวมถึงให้ฟีเจอร์ที่จะใช้เวลาหลายสัปดาห์ถ้าสร้างเอง
สิ่งที่ควรสำรวจ:
- วิธีที่เอนจินเกมจัดระเบียบโค้ด – คุณจะทึ่งกับรูปแบบสุดเจ๋งที่เขาใช้
- เทคนิคประสิทธิภาพสำหรับเกมแคนวาสให้เล่นลื่นไหล
- ฟีเจอร์ JavaScript สมัยใหม่ที่ทำให้โค้ดสะอาดและดูแลง่ายขึ้น
- แนวทางต่างๆ ในการจัดการวัตถุเกมและความสัมพันธ์ของมัน
🎯 กรอบเวลาการเชี่ยวชาญอนิเมชันเกมของคุณ
timeline
title ความก้าวหน้าในการเรียนรู้การเคลื่อนไหวและการโต้ตอบในเกม
section พื้นฐานการเคลื่อนไหว (20 นาที)
หลักการแอนิเมชัน: แอนิเมชันแบบเฟรม
: การอัปเดตตำแหน่ง
: ระบบพิกัด
: การเคลื่อนไหวที่ราบรื่น
section ระบบเหตุการณ์ (25 นาที)
การป้อนข้อมูลผู้ใช้: การจัดการเหตุการณ์คีย์บอร์ด
: การป้องกันพฤติกรรมเริ่มต้น
: คุณสมบัติวัตถุเหตุการณ์
: การฟังระดับหน้าต่าง
section สถาปัตยกรรมเกม (30 นาที)
การออกแบบวัตถุ: รูปแบบการสืบทอด
: การสร้างคลาสฐาน
: พฤติกรรมเฉพาะทาง
: อินเทอร์เฟซแบบพหุรูป
section รูปแบบการสื่อสาร (35 นาที)
การใช้งาน Pub/Sub: ตัวส่งเหตุการณ์
: ค่าคงที่ของข้อความ
: การผูกมัดแบบหย่อน
: การบูรณาการระบบ
section ความชำนาญวงจรเกม (40 นาที)
ระบบเรียลไทม์: การควบคุมอัตราเฟรม
: รอบการอัปเดต/เรนเดอร์
: การจัดการสถานะ
: การเพิ่มประสิทธิภาพ
section เทคนิคขั้นสูง (45 นาที)
ฟีเจอร์ระดับมืออาชีพ: การตรวจจับการชน
: การจำลองฟิสิกส์
: เครื่องสถานะ
: ระบบคอมโพเนนต์
section แนวคิดเครื่องยนต์เกม (1 สัปดาห์)
ความเข้าใจเฟรมเวิร์ก: ระบบเอนทิตี-คอมโพเนนต์
: กราฟฉาก
: ท่อส่งสินทรัพย์
: การวิเคราะห์ประสิทธิภาพ
section ทักษะการผลิต (1 เดือน)
การพัฒนามืออาชีพ: การจัดระเบียบโค้ด
: การร่วมมือทีม
: กลยุทธ์การทดสอบ
: การเพิ่มประสิทธิภาพการเผยแพร่
🛠️ สรุปชุดเครื่องมือพัฒนาเกมของคุณ
หลังจากจบบทเรียนนี้ คุณได้ชำนาญ:
- หลักการอนิเมชัน: การเคลื่อนไหวแบบเฟรมและการเปลี่ยนผ่านที่ลื่นไหล
- โปรแกรมขับเคลื่อนด้วยเหตุการณ์: การจัดการอินพุตด้วยแป้นพิมพ์แบบมีการจัดการเหตุการณ์ถูกต้อง
- การออกแบบเชิงวัตถุ: โครงสร้างการสืบทอดและอินเทอร์เฟซพอลิมอร์ฟิก
- รูปแบบการสื่อสาร: สถาปัตยกรรม pub/sub เพื่อโค้ดที่ดูแลรักษาง่าย
- โครงสร้างลูปเกม: การอัปเดตและวาดภาพแบบเรียลไทม์
- ระบบอินพุต: การแมปการควบคุมผู้ใช้พร้อมป้องกันพฤติกรรมดีฟอลต์
- การจัดการทรัพยากร: การโหลดสไปรต์และเทคนิคการเรนเดอร์ที่มีประสิทธิภาพ
⚡ สิ่งที่คุณทำได้ใน 5 นาทีถัดไป
- เปิดคอนโซลในเบราว์เซอร์แล้วลอง
addEventListener('keydown', console.log)เพื่อตรวจเหตุการณ์แป้นพิมพ์ - สร้าง div ง่ายๆ แล้วเคลื่อนย้ายโดยใช้ปุ่มลูกศร
- ทดลองใช้
setIntervalเพื่อสร้างการเคลื่อนที่ต่อเนื่อง - ลองป้องกันพฤติกรรมดีฟอลต์ด้วย
event.preventDefault()
🎯 สิ่งที่ทำได้ในชั่วโมงนี้
- ทำแบบทดสอบหลังเรียนและเข้าใจโปรแกรมขับเคลื่อนด้วยเหตุการณ์
- สร้างยานฮีโร่ที่เคลื่อนที่ได้ด้วยแป้นพิมพ์ครบถ้วน
- ใช้รูปแบบการเคลื่อนที่ศัตรูที่ลื่นไหล
- เพิ่มขอบเขตไม่ให้วัตถุเกมออกนอกหน้าจอ
- สร้างระบบตรวจจับการชนเบื้องต้นระหว่างวัตถุเกม
📅 การเดินทางอนิเมชันตลอดสัปดาห์ของคุณ
- สร้างเกมอวกาศเต็มรูปแบบที่มีการเคลื่อนไหวและปฏิสัมพันธ์ที่ปรับแต่งแล้ว
- เพิ่มรูปแบบการเคลื่อนที่ขั้นสูง เช่น เส้นโค้ง, การเร่งความเร็ว และฟิสิกส์
- สร้างการเปลี่ยนผ่านและฟังก์ชัน easing ที่ลื่นไหล
- สร้างเอฟเฟกต์อนุภาคและระบบสัญญาณภาพ
- ปรับประสิทธิภาพเกมให้เล่นลื่นไหลที่ 60fps
- เพิ่มการควบคุมด้วยสัมผัสมือถือและดีไซน์ตอบสนอง
🌟 การพัฒนาแบบอินเทอร์แอคทีฟตลอดเดือนของคุณ
- สร้างแอปพลิเคชันเชิงโต้ตอบซับซ้อนด้วยระบบอนิเมชันขั้นสูง
- เรียนรู้ไลบรารีอนิเมชันเช่น GSAP หรือสร้างเอนจินอนิเมชันของตัวเอง
- มีส่วนร่วมพัฒนาเกมและโปรเจกต์อนิเมชันแบบโอเพนซอร์ส
- เชี่ยวชาญการปรับประสิทธิภาพสำหรับแอปกราฟิกหนัก
- สร้างเนื้อหาการเรียนรู้เกี่ยวกับการพัฒนาเกมและอนิเมชัน
- สร้างพอร์ตโฟลิโอแสดงทักษะโปรแกรมเชิงโต้ตอบขั้นสูง
แอปพลิเคชันจริง: ทักษะอนิเมชันเกมของคุณนำไปใช้ได้กับ:
- เว็บแอปพลิเคชันเชิงโต้ตอบ: แดชบอร์ดแบบไดนามิกและอินเทอร์เฟซเรียลไทม์
- การแสดงข้อมูล: แผนภูมิอนิเมชันและกราฟิกเชิงโต้ตอบ
- ซอฟต์แวร์การศึกษา: การจำลองเชิงโต้ตอบและเครื่องมือเรียนรู้
- พัฒนามือถือ: เกมสัมผัสและการจัดการท่าทาง
- แอปเดสก์ท็อป: แอป Electron พร้อมอนิเมชันลื่นไหล
- อนิเมชันเว็บ: ไลบรารีอนิเมชัน CSS และ JavaScript
ทักษะมืออาชีพที่ได้รับ: ตอนนี้คุณสามารถ:
- ออกแบบสถาปัตยกรรม ระบบขับเคลื่อนด้วยเหตุการณ์ที่ปรับขยายได้ตามความซับซ้อน
- สร้างอนิเมชันลื่นไหล โดยใช้หลักคณิตศาสตร์
- ดีบัก ระบบปฏิสัมพันธ์ซับซ้อนด้วยเครื่องมือพัฒนาในเบราว์เซอร์
- ปรับประสิทธิภาพ เกมสำหรับอุปกรณ์และเบราว์เซอร์ต่างๆ
- ออกแบบ โครงสร้างโค้ดที่ดูแลรักษาได้โดยใช้รูปแบบที่พิสูจน์แล้ว
ความเข้าใจแนวคิดพัฒนาเกม:
- การจัดการเฟรมเรต: เข้าใจ FPS และการควบคุมเวลา
- การจัดการอินพุต: ระบบเหตุการณ์และแป้นพิมพ์ข้ามแพลตฟอร์ม
- วงจรชีวิตวัตถุ: รูปแบบการสร้าง, อัปเดต และทำลาย
- การซิงโครไนซ์สถานะ: รักษาสถานะเกมให้สอดคล้องระหว่างเฟรม
- สถาปัตยกรรมเหตุการณ์: การสื่อสารแบบแยกส่วนระหว่างระบบเกม
ขั้นถัดไป: คุณพร้อมเพิ่มระบบตรวจจับการชน, ระบบคะแนน, เอฟเฟกต์เสียง หรือสำรวจเฟรมเวิร์กเกมสมัยใหม่ เช่น Phaser หรือ Three.js!
🌟 ความสำเร็จ: คุณได้สร้างระบบเกมเชิงโต้ตอบครบสมบูรณ์ด้วยสถาปัตยกรรมมืออาชีพแล้ว!
การบ้าน
ข้อจำกัดความรับผิดชอบ: เอกสารนี้ได้รับการแปลโดยใช้บริการแปลด้วย AI Co-op Translator แม้ว่าเราจะพยายามให้ความถูกต้องสูงสุด แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่แม่นยำ เอกสารต้นฉบับในภาษาต้นทางควรถูกพิจารณาเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลโดยมนุษย์มืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดใดๆ ที่เกิดจากการใช้การแปลนี้