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/3-moving-elements-around
softchris a7d39944e9
🌐 Update translations via Co-op Translator
1 month ago
..
README.md 🌐 Update translations via Co-op Translator 1 month ago
assignment.md 🌐 Update translations via Co-op Translator 1 month ago

README.md

สร้างเกมอวกาศ ตอนที่ 3: เพิ่มการเคลื่อนไหว

ลองนึกถึงเกมโปรดของคุณ สิ่งที่ทำให้เกมน่าดึงดูดไม่ใช่แค่กราฟิกที่สวยงาม แต่เป็นวิธีที่ทุกอย่างเคลื่อนไหวและตอบสนองต่อการกระทำของคุณ ตอนนี้เกมอวกาศของคุณเหมือนภาพวาดที่สวยงาม แต่เรากำลังจะเพิ่มการเคลื่อนไหวเพื่อทำให้มันมีชีวิตชีวา

เมื่อวิศวกรของ NASA เขียนโปรแกรมคอมพิวเตอร์นำทางสำหรับภารกิจ Apollo พวกเขาเผชิญกับความท้าทายที่คล้ายกัน: จะทำให้ยานอวกาศตอบสนองต่อการควบคุมของนักบินในขณะที่ยังคงรักษาการปรับเส้นทางอัตโนมัติได้อย่างไร หลักการที่เราจะเรียนรู้ในวันนี้สะท้อนแนวคิดเดียวกัน การจัดการการเคลื่อนไหวที่ควบคุมโดยผู้เล่นควบคู่ไปกับพฤติกรรมของระบบอัตโนมัติ

ในบทเรียนนี้ คุณจะได้เรียนรู้วิธีทำให้ยานอวกาศลอยไปบนหน้าจอ ตอบสนองต่อคำสั่งของผู้เล่น และสร้างรูปแบบการเคลื่อนไหวที่ราบรื่น เราจะอธิบายทุกอย่างให้เข้าใจง่ายและเป็นขั้นตอน

เมื่อจบบทเรียนนี้ ผู้เล่นจะสามารถบังคับยานฮีโร่ของพวกเขาไปรอบ ๆ หน้าจอ ในขณะที่ยานศัตรูลาดตระเวนอยู่ด้านบน และที่สำคัญที่สุด คุณจะเข้าใจหลักการสำคัญที่ขับเคลื่อนระบบการเคลื่อนไหวในเกม

แบบทดสอบก่อนเรียน

แบบทดสอบก่อนเรียน

ทำความเข้าใจการเคลื่อนไหวในเกม

เกมจะมีชีวิตชีวาเมื่อสิ่งต่าง ๆ เริ่มเคลื่อนไหว และโดยพื้นฐานแล้วมีสองวิธีที่สิ่งนี้เกิดขึ้น:

  • การเคลื่อนไหวที่ควบคุมโดยผู้เล่น: เมื่อคุณกดปุ่มหรือคลิกเมาส์ สิ่งต่าง ๆ จะเคลื่อนไหว นี่คือการเชื่อมต่อโดยตรงระหว่างคุณกับโลกของเกม
  • การเคลื่อนไหวอัตโนมัติ: เมื่อเกมตัดสินใจเคลื่อนย้ายสิ่งต่าง ๆ เอง เช่น ยานศัตรูที่ต้องลาดตระเวนบนหน้าจอไม่ว่าคุณจะทำอะไรหรือไม่ก็ตาม

การทำให้วัตถุเคลื่อนที่บนหน้าจอคอมพิวเตอร์นั้นง่ายกว่าที่คุณคิด จำพิกัด x และ y จากชั้นเรียนคณิตศาสตร์ได้ไหม? นั่นแหละที่เรากำลังทำงานด้วย เมื่อกาลิเลโอเฝ้าสังเกตดวงจันทร์ของดาวพฤหัสบดีในปี 1610 เขาก็ทำสิ่งเดียวกัน วางตำแหน่งตามเวลาเพื่อทำความเข้าใจรูปแบบการเคลื่อนไหว

การเคลื่อนย้ายสิ่งต่าง ๆ บนหน้าจอเหมือนกับการสร้างภาพเคลื่อนไหวแบบพลิกหน้า คุณต้องทำตามสามขั้นตอนง่าย ๆ นี้:

  1. อัปเดตตำแหน่ง เปลี่ยนตำแหน่งของวัตถุ (อาจจะเลื่อนไปทางขวา 5 พิกเซล)
  2. ลบเฟรมเก่า ล้างหน้าจอเพื่อไม่ให้เห็นร่องรอยที่หลงเหลือ
  3. วาดเฟรมใหม่ วางวัตถุในตำแหน่งใหม่

ทำสิ่งนี้เร็วพอ แล้วบูม! คุณจะได้การเคลื่อนไหวที่ราบรื่นและรู้สึกเป็นธรรมชาติสำหรับผู้เล่น

นี่คือตัวอย่างในโค้ด:

// Set the hero's location
hero.x += 5;
// Clear the rectangle that hosts the hero
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Redraw the game background and hero
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.drawImage(heroImg, hero.x, hero.y);

สิ่งที่โค้ดนี้ทำ:

  • อัปเดต พิกัด x ของฮีโร่โดย 5 พิกเซลเพื่อเคลื่อนที่ในแนวนอน
  • ล้าง พื้นที่แคนวาสทั้งหมดเพื่อลบเฟรมก่อนหน้า
  • เติม พื้นหลังของแคนวาสด้วยสีดำ
  • วาดใหม่ ภาพฮีโร่ในตำแหน่งใหม่

คุณคิดว่าการวาดฮีโร่ใหม่หลายเฟรมต่อวินาทีอาจส่งผลต่อประสิทธิภาพได้อย่างไร? อ่านเพิ่มเติมเกี่ยวกับ ทางเลือกสำหรับรูปแบบนี้

จัดการเหตุการณ์คีย์บอร์ด

นี่คือจุดที่เราจะเชื่อมโยงการป้อนข้อมูลของผู้เล่นกับการกระทำในเกม เมื่อมีคนกด spacebar เพื่อยิงเลเซอร์หรือกดปุ่มลูกศรเพื่อหลบดาวเคราะห์น้อย เกมของคุณต้องตรวจจับและตอบสนองต่อการป้อนข้อมูลนั้น

เหตุการณ์คีย์บอร์ดเกิดขึ้นในระดับหน้าต่าง หมายความว่าหน้าต่างเบราว์เซอร์ทั้งหมดของคุณกำลังฟังการกดปุ่มเหล่านั้น ในทางกลับกัน การคลิกเมาส์สามารถผูกกับองค์ประกอบเฉพาะ (เช่น การคลิกปุ่ม) สำหรับเกมอวกาศของเรา เราจะเน้นที่การควบคุมด้วยคีย์บอร์ดเพราะนั่นคือสิ่งที่ให้ความรู้สึกเหมือนเกมอาร์เคดคลาสสิก

สิ่งนี้ทำให้ฉันนึกถึงวิธีที่ผู้ปฏิบัติการโทรเลขในศตวรรษที่ 19 ต้องแปลการป้อนข้อมูลรหัสมอร์สให้เป็นข้อความที่มีความหมาย เรากำลังทำสิ่งที่คล้ายกัน โดยแปลงการกดปุ่มให้เป็นคำสั่งในเกม

ในการจัดการเหตุการณ์ คุณต้องใช้เมธอด addEventListener() ของหน้าต่างและให้พารามิเตอร์สองตัวเป็นอินพุต พารามิเตอร์แรกคือชื่อของเหตุการณ์ เช่น keyup พารามิเตอร์ที่สองคือฟังก์ชันที่จะถูกเรียกใช้เมื่อเหตุการณ์เกิดขึ้น

ตัวอย่าง:

window.addEventListener('keyup', (evt) => {
  // evt.key = string representation of the key
  if (evt.key === 'ArrowUp') {
    // do something
  }
});

การอธิบายสิ่งที่เกิดขึ้นในที่นี้:

  • ฟัง เหตุการณ์คีย์บอร์ดในหน้าต่างทั้งหมด
  • จับ ออบเจ็กต์เหตุการณ์ที่มีข้อมูลเกี่ยวกับปุ่มที่ถูกกด
  • ตรวจสอบ ว่าปุ่มที่กดตรงกับปุ่มเฉพาะหรือไม่ (ในกรณีนี้คือปุ่มลูกศรขึ้น)
  • ดำเนินการ โค้ดเมื่อเงื่อนไขตรงกัน

สำหรับเหตุการณ์คีย์ มีสองคุณสมบัติในเหตุการณ์ที่คุณสามารถใช้เพื่อดูว่าปุ่มใดถูกกด:

  • key - เป็นตัวแทนข้อความของปุ่มที่กด เช่น 'ArrowUp'
  • keyCode - เป็นตัวแทนตัวเลข เช่น 37 ซึ่งตรงกับ ArrowLeft

การจัดการเหตุการณ์คีย์มีประโยชน์นอกเหนือจากการพัฒนาเกม คุณคิดว่าเทคนิคนี้สามารถนำไปใช้ในด้านอื่น ๆ ได้อย่างไร?

ปุ่มพิเศษ: ข้อควรระวัง!

บางปุ่มมีพฤติกรรมในตัวเบราว์เซอร์ที่อาจรบกวนเกมของคุณ ปุ่มลูกศรเลื่อนหน้า และ spacebar กระโดดลง พฤติกรรมที่คุณไม่ต้องการเมื่อมีคนพยายามควบคุมยานอวกาศของพวกเขา

เราสามารถป้องกันพฤติกรรมเริ่มต้นเหล่านี้และให้เกมของเราจัดการการป้อนข้อมูลแทน สิ่งนี้คล้ายกับวิธีที่โปรแกรมเมอร์คอมพิวเตอร์ยุคแรกต้องเขียนทับการขัดจังหวะของระบบเพื่อสร้างพฤติกรรมที่กำหนดเอง เราแค่ทำในระดับเบราว์เซอร์ นี่คือวิธี:

const onKeyDown = function (e) {
  console.log(e.keyCode);
  switch (e.keyCode) {
    case 37:
    case 39:
    case 38:
    case 40: // Arrow keys
    case 32:
      e.preventDefault();
      break; // Space
    default:
      break; // do not block other keys
  }
};

window.addEventListener('keydown', onKeyDown);

การทำความเข้าใจโค้ดป้องกันนี้:

  • ตรวจสอบ รหัสปุ่มเฉพาะที่อาจทำให้เกิดพฤติกรรมเบราว์เซอร์ที่ไม่ต้องการ
  • ป้องกัน การกระทำเริ่มต้นของเบราว์เซอร์สำหรับปุ่มลูกศรและ spacebar
  • อนุญาต ให้ปุ่มอื่นทำงานตามปกติ
  • ใช้ e.preventDefault() เพื่อหยุดพฤติกรรมในตัวของเบราว์เซอร์

การเคลื่อนไหวที่เกิดจากเกม

ตอนนี้เรามาพูดถึงวัตถุที่เคลื่อนไหวโดยไม่มีการป้อนข้อมูลจากผู้เล่น ลองนึกถึงยานศัตรูที่ล่องลอยบนหน้าจอ กระสุนที่บินเป็นเส้นตรง หรือเมฆที่ลอยอยู่ในพื้นหลัง การเคลื่อนไหวอัตโนมัตินี้ทำให้โลกของเกมของคุณรู้สึกมีชีวิตชีวาแม้ไม่มีใครแตะต้องการควบคุม

เราใช้ตัวจับเวลาที่มีอยู่ใน JavaScript เพื่ออัปเดตตำแหน่งในช่วงเวลาปกติ แนวคิดนี้คล้ายกับวิธีการทำงานของนาฬิกาลูกตุ้ม กลไกปกติที่กระตุ้นการกระทำที่สม่ำเสมอและตรงเวลา นี่คือวิธีที่ง่าย:

const id = setInterval(() => {
  // Move the enemy on the y axis
  enemy.y += 10;
}, 100);

สิ่งที่โค้ดการเคลื่อนไหวนี้ทำ:

  • สร้าง ตัวจับเวลาที่ทำงานทุก ๆ 100 มิลลิวินาที
  • อัปเดต พิกัด y ของศัตรูโดย 10 พิกเซลทุกครั้ง
  • เก็บ ID ของช่วงเวลาเพื่อหยุดมันในภายหลังหากจำเป็น
  • เคลื่อนย้าย ศัตรูลงบนหน้าจอโดยอัตโนมัติ

วงลูปของเกม

นี่คือแนวคิดที่ผูกทุกอย่างเข้าด้วยกัน วงลูปของเกม หากเกมของคุณเป็นภาพยนตร์ วงลูปของเกมจะเป็นเครื่องฉายภาพยนตร์ที่แสดงเฟรมต่อเฟรมอย่างรวดเร็วจนทุกอย่างดูเหมือนเคลื่อนไหวอย่างราบรื่น

ทุกเกมมีวงลูปเหล่านี้ทำงานอยู่เบื้องหลัง เป็นฟังก์ชันที่อัปเดตวัตถุเกมทั้งหมด วาดหน้าจอใหม่ และทำซ้ำกระบวนการนี้อย่างต่อเนื่อง สิ่งนี้ช่วยติดตามฮีโร่ของคุณ ศัตรูทั้งหมด เลเซอร์ที่บินไปรอบ ๆ สถานะของเกมทั้งหมด

แนวคิดนี้ทำให้ฉันนึกถึงวิธีที่นักวาดภาพยนตร์ยุคแรก ๆ เช่น Walt Disney ต้องวาดตัวละครใหม่เฟรมต่อเฟรมเพื่อสร้างภาพลวงตาของการเคลื่อนไหว เรากำลังทำสิ่งเดียวกัน เพียงแค่ใช้โค้ดแทนดินสอ

นี่คือสิ่งที่วงลูปของเกมมักจะมีลักษณะเป็นโค้ด:

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 Server ที่อยู่ http://localhost:5000
  • ให้บริการ ไฟล์เกมของคุณเพื่อทดสอบในเบราว์เซอร์

คำสั่งด้านบนจะเริ่ม HTTP Server ที่อยู่ http://localhost:5000 เปิดเบราว์เซอร์และใส่ที่อยู่นั้น ตอนนี้มันควรจะแสดงฮีโร่และศัตรูทั้งหมด; แต่ยังไม่มีอะไรเคลื่อนไหว ยัง!

เพิ่มโค้ด

  1. เพิ่มออบเจ็กต์เฉพาะ สำหรับ hero และ enemy และ game object ซึ่งควรมีคุณสมบัติ x และ y (จำส่วนเกี่ยวกับ Inheritance หรือ composition)

    คำแนะนำ 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() ที่แสดงวัตถุบนแคนวาส
    • ตั้งค่า ค่าเริ่มต้นสำหรับคุณสมบัติทั้งหมดที่คลาสลูกสามารถเขียนทับได้

    ตอนนี้ ขยาย GameObject เพื่อสร้าง Hero และ Enemy:

    class Hero extends GameObject {
      constructor(x, y) {
        super(x, y);
        this.width = 98;
        this.height = 75;
        this.type = "Hero";
        this.speed = 5;
      }
    }
    
    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()
  2. เพิ่มตัวจัดการเหตุการณ์คีย์ เพื่อจัดการการนำทางด้วยคีย์ (เคลื่อนย้ายฮีโร่ขึ้น/ลง ซ้าย/ขวา)

    จำไว้ ว่ามันเป็นระบบคาร์ทีเซียน มุมบนซ้ายคือ 0,0 และอย่าลืมเพิ่มโค้ดเพื่อหยุด พฤติกรรมเริ่มต้น

    เคล็ดลับ: สร้างฟังก์ชัน onKeyDown ของคุณและผูกมันกับหน้าต่าง:

    const onKeyDown = function (e) {
      console.log(e.keyCode);
      // Add the code from the lesson above to stop default behavior
      switch (e.keyCode) {
        case 37:
        case 39:
        case 38:
        case 40: // Arrow keys
        case 32:
          e.preventDefault();
          break; // Space
        default:
          break; // do not block other keys
      }
    };
    
    window.addEventListener("keydown", onKeyDown);
    

    สิ่งที่ตัวจัดการเหตุการณ์นี้ทำ:

    • ฟัง เหตุการณ์ keydown ในหน้าต่างทั้งหมด
    • บันทึก รหัสคีย์เพื่อช่วยคุณดีบักว่าปุ่มใดถูกกด
    • ป้องกัน พฤติกรรมเริ่มต้นของเบราว์เซอร์สำหรับปุ่มลูกศรและ spacebar
    • อนุญาต ให้ปุ่มอื่นทำงานตามปกติ

    ตรวจสอบคอนโซลเบราว์เซอร์ของคุณ ณ จุดนี้ และดูการกดปุ่มที่ถูกบันทึกไว้

  3. นำไปใช้ Pub sub pattern สิ่งนี้จะช่วยให้โค้ดของคุณสะอาดเมื่อคุณทำตามส่วนที่เหลือ

    รูปแบบ Publish-Subscribe ช่วยจัดระเบียบโค้ดของคุณโดยแยกการตรวจจับเหตุการณ์ออกจากการจัดการเหตุการณ์ สิ่งนี้ทำให้โค้ดของคุณมีความเป็นโมดูลและดูแลรักษาได้ง่ายขึ้น

    ในการทำส่วนสุดท้ายนี้ คุณสามารถ:

    1. เพิ่มตัวฟังเหตุการณ์ ในหน้าต่าง:

      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);
        }
      });
      

    สิ่งที่ระบบเหตุการณ์นี้ทำ:

    • ตรวจจับ การป้อนข้อมูลคีย์บอร์ดและแปลงเป็นเหตุการณ์เกมที่กำหนดเอง
    • แยก การตรวจจับการป้อนข้อมูลออกจากตรรกะของเกม
    • ทำให้ การเปลี่ยนแปลงการควบคุมในภายหลังง่ายขึ้นโดยไม่กระทบต่อโค้ดเกม
    • อนุญาต ให้ระบบหลายระบบ
  • สร้าง ตารางของศัตรูโดยใช้ลูปซ้อนกัน
  • กำหนด ภาพศัตรูให้กับวัตถุศัตรูแต่ละตัว
  • เพิ่ม ศัตรูแต่ละตัวลงในอาร์เรย์วัตถุเกมแบบ global

และเพิ่มฟังก์ชัน createHero() เพื่อทำกระบวนการคล้ายกันสำหรับฮีโร่

```javascript
function createHero() {
  hero = new Hero(
    canvas.width / 2 - 45,
    canvas.height - canvas.height / 4
  );
  hero.img = heroImg;
  gameObjects.push(hero);
}
```

สิ่งที่การสร้างฮีโร่ทำ:

  • กำหนดตำแหน่ง ฮีโร่ให้อยู่ตรงกลางด้านล่างของหน้าจอ
  • กำหนด ภาพฮีโร่ให้กับวัตถุฮีโร่
  • เพิ่ม ฮีโร่ลงในอาร์เรย์วัตถุเกมเพื่อการแสดงผล

และสุดท้าย เพิ่มฟังก์ชัน drawGameObjects() เพื่อเริ่มการวาด

```javascript
function drawGameObjects(ctx) {
  gameObjects.forEach(go => go.draw(ctx));
}
```

ทำความเข้าใจฟังก์ชันการวาด:

  • วนลูป ผ่านวัตถุเกมทั้งหมดในอาร์เรย์
  • เรียกใช้ เมธอด draw() บนวัตถุแต่ละตัว
  • ส่งผ่าน context ของ canvas เพื่อให้วัตถุสามารถแสดงผลตัวเองได้

ศัตรูของคุณควรเริ่มเคลื่อนที่เข้าหายานอวกาศฮีโร่ของคุณ!
}
}
```

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() เพื่อเริ่มการวาด

```javascript
function drawGameObjects(ctx) {
  gameObjects.forEach(go => go.draw(ctx));
}
```

ศัตรูของคุณควรเริ่มเคลื่อนที่เข้าหายานอวกาศฮีโร่ของคุณ!


GitHub Copilot Agent Challenge 🚀

นี่คือความท้าทายที่จะช่วยปรับปรุงความสมบูรณ์ของเกมของคุณ: การเพิ่มขอบเขตและการควบคุมที่ลื่นไหล ปัจจุบันฮีโร่ของคุณสามารถบินออกนอกหน้าจอได้ และการเคลื่อนไหวอาจดูไม่ราบรื่น

ภารกิจของคุณ: ทำให้ยานอวกาศของคุณรู้สึกสมจริงมากขึ้นโดยการเพิ่มขอบเขตหน้าจอและการควบคุมที่ลื่นไหล นี่คล้ายกับระบบควบคุมการบินของ NASA ที่ป้องกันไม่ให้ยานอวกาศเกินพารามิเตอร์การปฏิบัติการที่ปลอดภัย

สิ่งที่ต้องสร้าง: สร้างระบบที่ทำให้ยานอวกาศฮีโร่ของคุณอยู่ในหน้าจอ และทำให้การควบคุมรู้สึกลื่นไหล เมื่อผู้เล่นกดปุ่มลูกศรค้างไว้ ยานควรลื่นไหลต่อเนื่องแทนที่จะเคลื่อนที่เป็นขั้นๆ ลองพิจารณาเพิ่มการตอบสนองภาพเมื่อยานถึงขอบหน้าจอ อาจเป็นเอฟเฟกต์เล็กๆ เพื่อบ่งบอกถึงขอบพื้นที่เล่น

เรียนรู้เพิ่มเติมเกี่ยวกับ agent mode ที่นี่

🚀 Challenge

การจัดระเบียบโค้ดมีความสำคัญมากขึ้นเมื่อโปรเจกต์เติบโต คุณอาจสังเกตเห็นว่าไฟล์ของคุณเริ่มเต็มไปด้วยฟังก์ชัน ตัวแปร และคลาสที่ปะปนกัน นี่ทำให้นึกถึงวิศวกรที่จัดระเบียบโค้ดของภารกิจ Apollo ที่ต้องสร้างระบบที่ชัดเจนและดูแลรักษาได้ ซึ่งทีมหลายทีมสามารถทำงานร่วมกันได้

ภารกิจของคุณ:
คิดแบบสถาปนิกซอฟต์แวร์ คุณจะจัดระเบียบโค้ดของคุณอย่างไรเพื่อให้หกเดือนจากนี้ คุณ (หรือเพื่อนร่วมทีม) สามารถเข้าใจสิ่งที่เกิดขึ้นได้? แม้ว่าทุกอย่างจะยังอยู่ในไฟล์เดียวในตอนนี้ คุณสามารถสร้างการจัดระเบียบที่ดีขึ้นได้:

  • จัดกลุ่มฟังก์ชันที่เกี่ยวข้อง พร้อมหัวข้อคอมเมนต์ที่ชัดเจน
  • แยกความรับผิดชอบ - แยกตรรกะของเกมออกจากการแสดงผล
  • ใช้ชื่อที่สอดคล้องกัน สำหรับตัวแปรและฟังก์ชัน
  • สร้างโมดูล หรือ namespace เพื่อจัดระเบียบส่วนต่างๆ ของเกม
  • เพิ่มเอกสารประกอบ ที่อธิบายวัตถุประสงค์ของแต่ละส่วนสำคัญ

คำถามสะท้อน:

  • ส่วนใดของโค้ดของคุณที่เข้าใจยากที่สุดเมื่อคุณกลับมาดู?
  • คุณจะจัดระเบียบโค้ดอย่างไรเพื่อให้ง่ายขึ้นสำหรับคนอื่นที่จะมีส่วนร่วม?
  • จะเกิดอะไรขึ้นถ้าคุณต้องการเพิ่มฟีเจอร์ใหม่ เช่น power-ups หรือประเภทศัตรูที่แตกต่างกัน?

Post-Lecture Quiz

Post-lecture quiz

Review & Self Study

เรากำลังสร้างทุกอย่างตั้งแต่เริ่มต้น ซึ่งยอดเยี่ยมสำหรับการเรียนรู้ แต่มีความลับเล็กๆ น้อยๆ มีเฟรมเวิร์ก JavaScript ที่น่าทึ่งบางตัวที่สามารถจัดการงานหนักให้คุณได้ เมื่อคุณรู้สึกสบายใจกับพื้นฐานที่เราได้ครอบคลุมแล้ว คุ้มค่าที่จะ สำรวจสิ่งที่มีอยู่

คิดถึงเฟรมเวิร์กเหมือนมีชุดเครื่องมือที่ครบครันแทนที่จะสร้างเครื่องมือทุกชิ้นด้วยตัวเอง พวกมันสามารถแก้ปัญหาความท้าทายในการจัดระเบียบโค้ดที่เราพูดถึงได้มากมาย และยังมีฟีเจอร์ที่อาจใช้เวลาหลายสัปดาห์ในการสร้างเอง

สิ่งที่ควรสำรวจ:

  • วิธีที่ game engines จัดระเบียบโค้ด คุณจะทึ่งกับรูปแบบที่ชาญฉลาดที่พวกเขาใช้
  • เทคนิคการเพิ่มประสิทธิภาพเพื่อทำให้เกม canvas ทำงานได้อย่างราบรื่น
  • ฟีเจอร์ JavaScript สมัยใหม่ที่สามารถทำให้โค้ดของคุณสะอาดและดูแลรักษาได้ง่ายขึ้น
  • วิธีการต่างๆ ในการจัดการวัตถุเกมและความสัมพันธ์ของพวกมัน

Assignment

Comment your code


ข้อจำกัดความรับผิดชอบ:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI Co-op Translator แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลโดยอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้