|
|
1 month ago | |
|---|---|---|
| .. | ||
| README.md | 1 month ago | |
| assignment.md | 1 month ago | |
README.md
สร้างเกมอวกาศ ตอนที่ 2: วาดฮีโร่และมอนสเตอร์ลงบน Canvas
Canvas API เป็นหนึ่งในฟีเจอร์ที่ทรงพลังที่สุดของการพัฒนาเว็บสำหรับการสร้างกราฟิกแบบไดนามิกและโต้ตอบได้ในเบราว์เซอร์ของคุณ ในบทเรียนนี้ เราจะเปลี่ยน <canvas> HTML ที่ว่างเปล่าให้กลายเป็นโลกของเกมที่เต็มไปด้วยฮีโร่และมอนสเตอร์ ลองนึกถึง canvas ว่าเป็นกระดานศิลปะดิจิทัลที่โค้ดกลายเป็นภาพ
เราจะต่อยอดจากสิ่งที่คุณเรียนรู้ในบทเรียนก่อนหน้า และตอนนี้เราจะเจาะลึกในด้านภาพ คุณจะได้เรียนรู้วิธีโหลดและแสดงสไปรท์ของเกม การจัดตำแหน่งองค์ประกอบอย่างแม่นยำ และสร้างพื้นฐานภาพสำหรับเกมอวกาศของคุณ นี่คือสะพานเชื่อมระหว่างหน้าเว็บแบบคงที่และประสบการณ์แบบไดนามิกและโต้ตอบได้
เมื่อจบบทเรียนนี้ คุณจะมีฉากเกมที่สมบูรณ์พร้อมกับยานฮีโร่ที่วางตำแหน่งอย่างถูกต้องและการจัดรูปแบบศัตรูที่พร้อมสำหรับการต่อสู้ คุณจะเข้าใจวิธีที่เกมสมัยใหม่แสดงกราฟิกในเบราว์เซอร์ และได้รับทักษะในการสร้างประสบการณ์ภาพแบบโต้ตอบของคุณเอง มาสำรวจกราฟิกของ canvas และทำให้เกมอวกาศของคุณมีชีวิตชีวากันเถอะ!
แบบทดสอบก่อนเรียน
Canvas คืออะไร
แล้ว <canvas> คืออะไร? มันคือโซลูชันของ HTML5 สำหรับการสร้างกราฟิกและแอนิเมชันแบบไดนามิกในเบราว์เซอร์เว็บ ไม่เหมือนกับภาพหรือวิดีโอทั่วไปที่เป็นแบบคงที่ Canvas ให้คุณควบคุมระดับพิกเซลในทุกสิ่งที่ปรากฏบนหน้าจอ ซึ่งทำให้มันเหมาะสำหรับเกม การแสดงผลข้อมูล และศิลปะเชิงโต้ตอบ ลองนึกถึงมันว่าเป็นพื้นผิวการวาดที่สามารถเขียนโปรแกรมได้ โดยที่ JavaScript เป็นแปรงวาดของคุณ
โดยปกติแล้ว องค์ประกอบ canvas จะดูเหมือนสี่เหลี่ยมโปร่งใสที่ว่างเปล่าบนหน้าเว็บของคุณ แต่ศักยภาพที่แท้จริงของมันจะปรากฏเมื่อคุณใช้ JavaScript เพื่อวาดรูปร่าง โหลดภาพ สร้างแอนิเมชัน และทำให้สิ่งต่าง ๆ ตอบสนองต่อการโต้ตอบของผู้ใช้ มันคล้ายกับวิธีที่ผู้บุกเบิกกราฟิกคอมพิวเตอร์ในยุคแรก ๆ ที่ Bell Labs ในปี 1960 ต้องเขียนโปรแกรมพิกเซลทุกจุดเพื่อสร้างแอนิเมชันดิจิทัลครั้งแรก
✅ อ่าน เพิ่มเติมเกี่ยวกับ Canvas API บน MDN
นี่คือตัวอย่างการประกาศ canvas โดยทั่วไป ซึ่งเป็นส่วนหนึ่งของ body ของหน้าเว็บ:
<canvas id="myCanvas" width="200" height="100"></canvas>
สิ่งที่โค้ดนี้ทำ:
- ตั้งค่า attribute
idเพื่อให้คุณสามารถอ้างอิงถึงองค์ประกอบ canvas นี้ใน JavaScript - กำหนด
widthเป็นพิกเซลเพื่อควบคุมขนาดแนวนอนของ canvas - กำหนด
heightเป็นพิกเซลเพื่อกำหนดขนาดแนวตั้งของ canvas
การวาดรูปทรงเรขาคณิตง่าย ๆ
ตอนนี้คุณรู้แล้วว่า canvas คืออะไร ลองมาสำรวจวิธีการวาดบนมันกัน! Canvas ใช้ระบบพิกัดที่อาจจะคุ้นเคยจากชั้นเรียนคณิตศาสตร์ แต่มีจุดพลิกผันสำคัญที่เฉพาะเจาะจงสำหรับกราฟิกคอมพิวเตอร์
Canvas ใช้ระบบพิกัด Cartesian ที่มีแกน x (แนวนอน) และแกน y (แนวตั้ง) เพื่อกำหนดตำแหน่งของทุกสิ่งที่คุณวาด แต่มีความแตกต่างสำคัญ: ไม่เหมือนกับระบบพิกัดในชั้นเรียนคณิตศาสตร์ จุดเริ่มต้น (0,0) จะอยู่ที่มุมบนซ้าย โดยค่าของ x จะเพิ่มขึ้นเมื่อคุณเลื่อนไปทางขวา และค่าของ y จะเพิ่มขึ้นเมื่อคุณเลื่อนลง วิธีนี้มีต้นกำเนิดมาจากจอคอมพิวเตอร์ในยุคแรก ๆ ที่ลำแสงอิเล็กตรอนสแกนจากบนลงล่าง ทำให้มุมบนซ้ายเป็นจุดเริ่มต้นที่เป็นธรรมชาติ
ภาพจาก MDN
ในการวาดบน canvas คุณจะทำตามกระบวนการสามขั้นตอนเดียวกันที่เป็นพื้นฐานของกราฟิก canvas ทั้งหมด เมื่อคุณทำสิ่งนี้สองสามครั้ง มันจะกลายเป็นธรรมชาติ:
- อ้างอิงถึงองค์ประกอบ Canvas ของคุณจาก DOM (เหมือนกับองค์ประกอบ HTML อื่น ๆ)
- รับบริบทการเรนเดอร์ 2D – นี่คือเครื่องมือที่มีวิธีการวาดทั้งหมด
- เริ่มวาด! ใช้วิธีการในตัวของบริบทเพื่อสร้างกราฟิกของคุณ
นี่คือลักษณะของโค้ด:
// Step 1: Get the canvas element
const canvas = document.getElementById("myCanvas");
// Step 2: Get the 2D rendering context
const ctx = canvas.getContext("2d");
// Step 3: Set fill color and draw a rectangle
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 200, 200); // x, y, width, height
มาดูทีละขั้นตอน:
- เรา ดึงองค์ประกอบ canvas โดยใช้ ID และเก็บไว้ในตัวแปร
- เรา รับบริบทการเรนเดอร์ 2D – นี่คือชุดเครื่องมือที่เต็มไปด้วยวิธีการวาด
- เรา บอก canvas ว่าเราต้องการเติมสีแดงโดยใช้ property
fillStyle - เรา วาดสี่เหลี่ยมที่เริ่มต้นที่มุมบนซ้าย (0,0) ที่มีความกว้างและสูง 200 พิกเซล
✅ Canvas API ส่วนใหญ่เน้นที่รูปร่าง 2D แต่คุณสามารถวาดองค์ประกอบ 3D ลงในเว็บไซต์ได้; สำหรับสิ่งนี้ คุณอาจใช้ WebGL API
คุณสามารถวาดสิ่งต่าง ๆ ได้หลากหลายด้วย Canvas API เช่น:
- รูปร่างเรขาคณิต เราได้แสดงวิธีการวาดสี่เหลี่ยมแล้ว แต่ยังมีอีกมากมายที่คุณสามารถวาดได้
- ข้อความ คุณสามารถวาดข้อความด้วยฟอนต์และสีใดก็ได้ที่คุณต้องการ
- ภาพ คุณสามารถวาดภาพจากไฟล์ภาพ เช่น .jpg หรือ .png เป็นต้น
✅ ลองทำดู! คุณรู้วิธีวาดสี่เหลี่ยมแล้ว คุณสามารถวาดวงกลมลงบนหน้าได้หรือไม่? ลองดูภาพวาด Canvas ที่น่าสนใจบน CodePen นี่คือตัวอย่างที่ น่าประทับใจ
โหลดและวาดภาพ
การวาดรูปร่างพื้นฐานมีประโยชน์สำหรับการเริ่มต้น แต่เกมส่วนใหญ่ต้องการภาพจริง! สไปรท์ พื้นหลัง และพื้นผิวคือสิ่งที่ทำให้เกมมีความน่าสนใจทางภาพ การโหลดและแสดงภาพบน canvas ทำงานแตกต่างจากการวาดรูปร่างเรขาคณิต แต่ก็ง่ายเมื่อคุณเข้าใจกระบวนการ
เราจำเป็นต้องสร้างวัตถุ Image โหลดไฟล์ภาพของเรา (สิ่งนี้เกิดขึ้นแบบอะซิงโครนัส หมายถึง "ในพื้นหลัง") และวาดมันลงบน canvas เมื่อมันพร้อม วิธีนี้ช่วยให้ภาพของคุณแสดงผลได้อย่างถูกต้องโดยไม่ทำให้แอปพลิเคชันของคุณหยุดชะงักขณะโหลด
การโหลดภาพพื้นฐาน
const img = new Image();
img.src = 'path/to/my/image.png';
img.onload = () => {
// Image loaded and ready to be used
console.log('Image loaded successfully!');
};
สิ่งที่เกิดขึ้นในโค้ดนี้:
- เรา สร้างวัตถุ Image ใหม่เพื่อเก็บสไปรท์หรือพื้นผิวของเรา
- เรา บอกว่าต้องโหลดไฟล์ภาพใดโดยตั้งค่าเส้นทาง source
- เรา ฟังเหตุการณ์ load เพื่อให้เรารู้ว่าเมื่อใดภาพพร้อมใช้งาน
วิธีที่ดีกว่าในการโหลดภาพ
นี่คือวิธีที่มีประสิทธิภาพมากขึ้นในการจัดการการโหลดภาพที่นักพัฒนามืออาชีพใช้กันทั่วไป เราจะห่อการโหลดภาพในฟังก์ชันที่ใช้ Promise – วิธีนี้ซึ่งได้รับความนิยมเมื่อ JavaScript Promises กลายเป็นมาตรฐานใน ES6 ทำให้โค้ดของคุณมีการจัดระเบียบมากขึ้นและจัดการข้อผิดพลาดได้อย่างดี:
function loadAsset(path) {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = path;
img.onload = () => {
resolve(img);
};
img.onerror = () => {
reject(new Error(`Failed to load image: ${path}`));
};
});
}
// Modern usage with async/await
async function initializeGame() {
try {
const heroImg = await loadAsset('hero.png');
const monsterImg = await loadAsset('monster.png');
// Images are now ready to use
} catch (error) {
console.error('Failed to load game assets:', error);
}
}
สิ่งที่เราทำในที่นี้:
- ห่อตรรกะการโหลดภาพทั้งหมดใน Promise เพื่อให้เราจัดการได้ดีขึ้น
- เพิ่มการจัดการข้อผิดพลาดที่บอกเราจริง ๆ เมื่อมีบางอย่างผิดพลาด
- ใช้ไวยากรณ์ async/await ที่ทันสมัยเพราะมันอ่านง่ายมาก
- รวมบล็อก try/catch เพื่อจัดการปัญหาการโหลดอย่างสุภาพ
เมื่อภาพของคุณโหลดเสร็จ การวาดมันลงบน canvas นั้นค่อนข้างตรงไปตรงมา:
async function renderGameScreen() {
try {
// Load game assets
const heroImg = await loadAsset('hero.png');
const monsterImg = await loadAsset('monster.png');
// Get canvas and context
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
// Draw images to specific positions
ctx.drawImage(heroImg, canvas.width / 2, canvas.height / 2);
ctx.drawImage(monsterImg, 0, 0);
} catch (error) {
console.error('Failed to render game screen:', error);
}
}
มาดูทีละขั้นตอน:
- เรา โหลดภาพฮีโร่และมอนสเตอร์ในพื้นหลังโดยใช้ await
- เรา ดึงองค์ประกอบ canvas และรับบริบทการเรนเดอร์ 2D ที่เราต้องการ
- เรา จัดตำแหน่งภาพฮีโร่ตรงกลางโดยใช้คณิตศาสตร์พิกัดอย่างรวดเร็ว
- เรา วางภาพมอนสเตอร์ที่มุมบนซ้ายเพื่อเริ่มการจัดรูปแบบศัตรู
- เรา จับข้อผิดพลาดใด ๆ ที่อาจเกิดขึ้นระหว่างการโหลดหรือการเรนเดอร์
ถึงเวลาสร้างเกมของคุณแล้ว
ตอนนี้เราจะรวมทุกอย่างเข้าด้วยกันเพื่อสร้างพื้นฐานภาพของเกมอวกาศของคุณ คุณมีความเข้าใจที่มั่นคงเกี่ยวกับพื้นฐานของ canvas และเทคนิคการโหลดภาพ ดังนั้นส่วนที่ลงมือทำนี้จะนำคุณผ่านการสร้างหน้าจอเกมที่สมบูรณ์พร้อมสไปรท์ที่วางตำแหน่งอย่างเหมาะสม
สิ่งที่ต้องสร้าง
คุณจะสร้างหน้าเว็บที่มีองค์ประกอบ Canvas ซึ่งจะแสดงหน้าจอสีดำขนาด 1024*768 เราได้เตรียมภาพสองภาพให้คุณ:
ขั้นตอนที่แนะนำในการเริ่มต้นพัฒนา
ค้นหาไฟล์เริ่มต้นที่ถูกสร้างไว้ให้คุณในโฟลเดอร์ your-work โครงสร้างโปรเจกต์ของคุณควรมี:
your-work/
├── assets/
│ ├── enemyShip.png
│ └── player.png
├── index.html
├── app.js
└── package.json
สิ่งที่คุณกำลังทำงานด้วย:
- สไปรท์เกม อยู่ในโฟลเดอร์
assets/เพื่อให้ทุกอย่างเป็นระเบียบ - ไฟล์ HTML หลักของคุณ ตั้งค่าองค์ประกอบ canvas และเตรียมทุกอย่างให้พร้อม
- ไฟล์ JavaScript ที่คุณจะเขียนโค้ดการเรนเดอร์เกมทั้งหมด
- ไฟล์ package.json ที่ตั้งค่าเซิร์ฟเวอร์พัฒนาเพื่อให้คุณทดสอบได้ในเครื่อง
เปิดโฟลเดอร์นี้ใน Visual Studio Code เพื่อเริ่มพัฒนา คุณจะต้องมีสภาพแวดล้อมการพัฒนาในเครื่องที่มี Visual Studio Code, NPM และ Node.js ติดตั้งอยู่ หากคุณยังไม่มี npm ตั้งค่าในคอมพิวเตอร์ของคุณ นี่คือวิธีการติดตั้ง
เริ่มเซิร์ฟเวอร์พัฒนาของคุณโดยไปที่โฟลเดอร์ your-work:
cd your-work
npm start
คำสั่งนี้ทำสิ่งที่น่าสนใจ:
- เริ่มต้นเซิร์ฟเวอร์ในเครื่องที่
http://localhost:5000เพื่อให้คุณทดสอบเกมของคุณ - ให้บริการไฟล์ทั้งหมดของคุณอย่างถูกต้องเพื่อให้เบราว์เซอร์โหลดได้อย่างถูกต้อง
- เฝ้าดูไฟล์ของคุณสำหรับการเปลี่ยนแปลงเพื่อให้คุณพัฒนาได้อย่างราบรื่น
- ให้คุณสภาพแวดล้อมการพัฒนาระดับมืออาชีพเพื่อทดสอบทุกอย่าง
💡 หมายเหตุ: เบราว์เซอร์ของคุณจะแสดงหน้าเปล่าในตอนแรก – นั่นเป็นเรื่องปกติ! เมื่อคุณเพิ่มโค้ด ให้รีเฟรชเบราว์เซอร์เพื่อดูการเปลี่ยนแปลงของคุณ วิธีการพัฒนาแบบวนซ้ำนี้คล้ายกับวิธีที่ NASA สร้างคอมพิวเตอร์นำทาง Apollo – ทดสอบแต่ละส่วนก่อนที่จะรวมเข้ากับระบบใหญ่
เพิ่มโค้ด
เพิ่มโค้ดที่จำเป็นลงใน your-work/app.js เพื่อทำงานต่อไปนี้ให้เสร็จ:
-
วาด canvas พร้อมพื้นหลังสีดำ
💡 วิธีการ: ค้นหา TODO ใน
/app.jsและเพิ่มเพียงสองบรรทัด ตั้งค่าctx.fillStyleเป็นสีดำ จากนั้นใช้ctx.fillRect()เริ่มต้นที่ (0,0) พร้อมขนาดของ canvas ของคุณ ง่ายมาก! -
โหลดพื้นผิวเกม
💡 วิธีการ: ใช้
await loadAsset()เพื่อโหลดภาพผู้เล่นและศัตรูของคุณ เก็บไว้ในตัวแปรเพื่อให้คุณสามารถใช้มันในภายหลัง จำไว้ – มันจะไม่ปรากฏจนกว่าคุณจะวาดมันจริง ๆ! -
วาดยานฮีโร่ในตำแหน่งกลาง-ล่าง
💡 วิธีการ: ใช้
ctx.drawImage()เพื่อวางตำแหน่งฮีโร่ของคุณ สำหรับพิกัด x ลองใช้canvas.width / 2 - 45เพื่อวางตรงกลาง และสำหรับพิกัด y ใช้canvas.height - canvas.height / 4เพื่อวางในพื้นที่ด้านล่าง -
วาดรูปแบบมอนสเตอร์ 5×5
💡 วิธีการ: ค้นหาฟังก์ชัน
createEnemiesและตั้งค่าลูปซ้อนกัน คุณจะต้องทำคณิตศาสตร์สำหรับการเว้นระยะและการวางตำแหน่ง แต่ไม่ต้องกังวล – ฉันจะแสดงให้คุณเห็นว่าทำอย่างไร!
ก่อนอื่น กำหนดค่าคงที่สำหรับการจัดรูปแบบศัตรูที่เหมาะสม:
const ENEMY_TOTAL = 5;
const ENEMY_SPACING = 98;
const FORMATION_WIDTH = ENEMY_TOTAL * ENEMY_SPACING;
const START_X = (canvas.width - FORMATION_WIDTH) / 2;
const STOP_X = START_X + FORMATION_WIDTH;
มาดูว่าค่าคงที่เหล่านี้ทำอะไร:
- เรา ตั้งค่าศัตรู 5 ตัวต่อแถวและคอลัมน์ (กริด 5×5 ที่สวยงาม)
- เรา กำหนดระยะห่างระหว่างศัตรูเพื่อไม่ให้ดูแออัด
- เรา คำนวณความกว้างของรูปแบบทั้งหมด
- เรา หาจุดเริ่มต้นและจุดสิ้นสุดเพื่อให้รูปแบบดูสมดุล
จากนั้น สร้างลูปซ้อนกันเพื่อวาดรูปแบบศัตรู:
for (let x = START_X; x < STOP_X; x += ENEMY_SPACING) {
for (let y = 0; y < 50 * 5; y += 50) {
ctx.drawImage(enemyImg, x, y);
}
}
นี่คือสิ่งที่ลูปซ้อนกันนี้ทำ:
- ลูปด้านนอก เคลื่อนที่จากซ้ายไปขวาในรูปแบบของเรา
- ลูปด้านใน เคลื่อนที่จากบนลงล่างเพื่อสร้างแถวที่เรียบร้อย
- เรา วาดสไปรท์ศัตรูแต่ละตัวที่พิกัด x,y ที่เราคำนวณไว้
- ทุกอย่าง เว้นระยะห่างอย่างสม่ำเสมอเพื่อให้ดูเป็นมืออาชีพและเป็นระเบียบ
ผลลัพธ์
ผลลัพธ์ที่เสร็จสมบูรณ์ควรมีลักษณะดังนี้:
วิธีแก้ปัญหา
กรุณาลองแก้ปัญหาด้วยตัวเองก่อน แต่ถ้าคุณติดขัด ลองดู วิธีแก้ปัญหา
ความท้าทาย GitHub Copilot Agent 🚀
ใช้โหมด Agent เพื่อทำความท้าทายต่อไปนี้ให้สำเร็จ:
คำอธิบาย: เพิ่มเอฟเฟกต์ภาพและองค์ประกอบแบบโต้ตอบใน canvas เกมอวกาศของคุณโดยใช้เทคนิค Canvas API ที่คุณได้เรียนรู้
คำสั่ง: สร้างไฟล์ใหม่ชื่อ enhanced-canvas.html พร้อม canvas ที่แสดงดาวที่เคลื่อนไหวในพื้นหลัง แถบสุขภาพที่เต้นเป็นจังหวะสำหรับยานฮีโร่ และยานศัตรูที่เคลื่อนที่ลงอย่างช้า ๆ รวมโค้ด JavaScript ที่วาดดาวที่กระพริบโดยใช้ตำแหน่งและความทึบแบบสุ่ม ใช้แถบสุขภาพที่เปลี่ยนสีตามระดับสุขภาพ (เขียว > เหลือง > แดง) และทำให้ยานศัตรูเคลื่อนที่ลงหน้าจอด้วยความเร็วต่างกัน
เรียนรู้เพิ่มเติมเกี่ยวกับ [โหมด Agent](https://code
ข้อจำกัดความรับผิดชอบ:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI Co-op Translator แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราจะไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้



