15 KiB
建立太空遊戲第二部分:將英雄和怪物繪製到 Canvas
Canvas API 是網頁開發中最強大的功能之一,可以直接在瀏覽器中創建動態、互動式的圖形。在本課程中,我們將把空白的 HTML <canvas> 元素轉變成充滿英雄和怪物的遊戲世界。將 Canvas 想像成你的數位畫板,程式碼在這裡變成了視覺效果。
我們將基於上一課所學的內容,深入探討視覺方面。你將學習如何載入和顯示遊戲精靈圖(sprites),精確定位元素,並為你的太空遊戲建立視覺基礎。這將把靜態網頁與動態互動體驗之間的差距拉近。
在本課程結束時,你將擁有一個完整的遊戲場景,英雄飛船正確定位,敵人陣型準備迎戰。你將了解現代遊戲如何在瀏覽器中渲染圖形,並獲得創建自己互動式視覺體驗的技能。讓我們一起探索 Canvas 圖形,讓你的太空遊戲活起來吧!
課前測驗
Canvas 是什麼?
那麼,究竟什麼是 <canvas> 元素呢?它是 HTML5 提供的一種解決方案,用於在網頁瀏覽器中創建動態圖形和動畫。與靜態的圖片或影片不同,Canvas 讓你可以對螢幕上出現的每個像素進行控制。這使得它非常適合用於遊戲、數據可視化和互動藝術。可以將它想像成一個可編程的繪圖表面,而 JavaScript 則是你的畫筆。
預設情況下,Canvas 元素在頁面上看起來像是一個空白的透明矩形。但它的潛力就在於此!當你使用 JavaScript 繪製形狀、載入圖片、創建動畫並讓元素響應使用者互動時,它的真正威力才會展現出來。這類似於 1960 年代貝爾實驗室的早期電腦圖形先驅,他們需要編程每個像素來創建第一批數位動畫。
✅ 閱讀 更多關於 Canvas API 的內容(MDN)。
以下是它通常的宣告方式,作為頁面 <body> 的一部分:
<canvas id="myCanvas" width="200" height="100"></canvas>
這段程式碼的作用:
- 設置
id屬性,以便你可以在 JavaScript 中引用這個特定的 Canvas 元素 - 定義 Canvas 的寬度(以像素為單位),以控制其水平大小
- 確定 Canvas 的高度(以像素為單位),以決定其垂直尺寸
繪製簡單幾何圖形
現在你已經知道 Canvas 元素是什麼了,讓我們來探索如何在其上進行繪製!Canvas 使用的座標系統可能讓你聯想到數學課,但在電腦圖形中有一個重要的不同之處。
Canvas 使用笛卡爾座標系統,具有 x 軸(水平)和 y 軸(垂直),用於定位你繪製的所有內容。但這裡有一個關鍵的不同:與數學課上的座標系統不同,原點 (0,0) 是從左上角開始的,x 值向右增加,y 值向下增加。這種方式源於早期電腦顯示器,電子束從上到下掃描,使左上角成為自然的起始點。
圖片來源:MDN
要在 Canvas 元素上繪製,你需要遵循以下三個步驟,這是所有 Canvas 圖形的基礎。一旦你熟悉了這個過程,它就會變得非常自然:
- 從 DOM 中獲取 Canvas 元素的引用(就像其他 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 我們想用紅色填充,使用
fillStyle屬性 - 我們 繪製 一個矩形,從左上角 (0,0) 開始,寬度和高度均為 200 像素
✅ Canvas API 主要專注於 2D 圖形,但你也可以在網站上繪製 3D 元素;為此,你可能需要使用 WebGL API。
使用 Canvas API,你可以繪製各種內容,例如:
- 幾何形狀,我們已展示如何繪製矩形,但還有更多形狀可以繪製。
- 文字,你可以使用任何字體和顏色繪製文字。
- 圖片,你可以基於圖片資源(例如 .jpg 或 .png)繪製圖片。
✅ 試試看!你已經知道如何繪製矩形,能否在頁面上繪製一個圓形?看看 CodePen 上一些有趣的 Canvas 繪圖。這裡有一個特別令人印象深刻的例子。
載入並繪製圖片資源
繪製基本形狀對於入門非常有用,但大多數遊戲需要真正的圖片!精靈圖、背景和紋理是讓遊戲具有視覺吸引力的關鍵。在 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 對象來保存精靈圖或紋理
- 我們 指定 要載入的圖片檔案,通過設置來源路徑
- 我們 監聽 載入事件,以便確切知道圖片何時準備好使用
更好的圖片載入方式
以下是一種更健全的圖片載入方式,專業開發者通常使用這種方法。我們將圖片載入邏輯包裝在基於 Promise 的函數中——這種方法在 ES6 標準化 JavaScript Promises 後變得流行,使你的程式碼更有組織性並能優雅地處理錯誤:
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 建造阿波羅導航電腦的方式——在整合到更大的系統之前測試每個組件。
添加程式碼
在 your-work/app.js 中添加所需程式碼,完成以下任務:
-
繪製黑色背景的 Canvas
💡 方法:在
/app.js中找到 TODO,添加兩行程式碼。設置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 API 技術,為你的太空遊戲 Canvas 添加視覺效果和互動元素。
提示: 創建一個名為 enhanced-canvas.html 的新檔案,Canvas 上顯示背景中動畫星星、英雄飛船的脈動生命條,以及緩慢向下移動的敵人飛船。包含 JavaScript 程式碼,繪製隨機位置和透明度的閃爍星星,實現根據生命值變化顏色的生命條(綠色 > 黃色 > 紅色),並使敵人飛船以不同速度向下移動。
了解更多關於 Agent 模式 的內容。
🚀 挑戰
你已經學習了使用 2D Canvas API 繪圖;看看 WebGL API,嘗試繪製一個 3D 物件。
課後測驗
回顧與自學
通過閱讀相關內容了解更多 Canvas API。
作業
免責聲明:
本文件已使用 AI 翻譯服務 Co-op Translator 進行翻譯。儘管我們努力確保準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。



