Charles Emmanuel S. Ndiaye
972c40d103
|
3 years ago | |
---|---|---|
.. | ||
README.es.md | 3 years ago | |
README.fr.md | 3 years ago | |
README.hi.md | 3 years ago | |
README.it.md | 3 years ago | |
README.ja.md | 3 years ago | |
README.ko.md | 3 years ago | |
README.ms.md | 3 years ago | |
README.zh-tw.md | 3 years ago | |
assignment.es.md | 4 years ago | |
assignment.fr.md | 3 years ago | |
assignment.hi.md | 4 years ago | |
assignment.it.md | 4 years ago | |
assignment.ja.md | 4 years ago | |
assignment.ko.md | 4 years ago | |
assignment.ms.md | 4 years ago | |
assignment.nl.md | 4 years ago | |
assignment.zh-tw.md | 4 years ago |
README.zh-tw.md
建立太空遊戲 Part 6:結束與重來
課前測驗
有許多方式可以表達遊戲中的結束狀態。這都取決於你這位遊戲開發者,定義遊戲結束的理由。假設我們討論這款已經開發許久的太空遊戲,以下是遊戲結束的理由:
N
艘敵軍艦艇被擊毀:如果你想將遊戲分成許多關卡,一種常見的方式是將每一關的破關門檻,定為擊毀N
艘敵軍艦艇。- 你的船艦已被擊毀:一定有遊戲,只要你的船艦被擊毀一次時,便判定你輸了這場遊戲。另一種可行概念是加入生命值系統。每次你的船艦被擊毀時,會扣除一條生命。一但你損失了所有性命,你便輸了這場遊戲。
- 你已經取得
N
點分數:另一種常見的結束狀態為分數門檻。取得分數的機制取決在你,常見的條件為摧毀敵艦、或是收集敵艦所掉落的道具。 - 完成關卡:這或許會涉及到許多種狀態,好比說:
X
艘艦艇已被擊毀、已取得Y
點分數或是收集特定的道具。
重新遊戲
如果玩家很享受你的遊戲,他們會想再重新遊玩一次。一旦因任何原因結束遊戲時,你應該要提供重新遊戲的方法。
✅ 想想看,什麼條件下會結束一款遊戲,而它們又是如何提示你重新遊玩。
建立目標
你需要為你的遊戲新增這些規則:
- 贏得遊戲。 一旦所有敵軍艦艇被擊毀時,你便贏得這場遊戲。請額外地顯示勝利訊息。
- 重新開始。 一旦你損失了所有性命,或是贏得了勝利,你應該提供方法來重新遊戲。記住!你需要重新初始化你的遊戲,所有遊戲的歷史紀錄會被移除。
建議步驟
在你的 your-work
子資料夾中,確認檔案是否建立完成。它應該包括:
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| life.png
-| index.html
-| app.js
-| package.json
開始 your_work
資料夾中的專案,輸入:
cd your-work
npm start
這會啟動 HTTP 伺服器並發布網址 http://localhost:5000
。開啟瀏覽器並輸入該網址。你的遊戲應該能被遊玩。
要點: 要避免在 Visual Studio Code 裡出現警告訊息,編輯函式
window.onload
以 is,而非 let 的方式呼叫gameLoopId
;並在檔案正上方獨立地宣告 gameLoopId:let gameLoopId;
。
加入程式碼
-
追蹤結束狀態。 新增程式碼來追蹤敵人的數量,利用下列函式判斷英雄艦艇是否被擊毀:
function isHeroDead() { return hero.life <= 0; } function isEnemiesDead() { const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead); return enemies.length === 0; }
-
加入訊息處理器。 編輯
eventEmitter
以處理這些狀態:eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => { first.dead = true; second.dead = true; hero.incrementPoints(); if (isEnemiesDead()) { eventEmitter.emit(Messages.GAME_END_WIN); } }); eventEmitter.on(Messages.COLLISION_ENEMY_HERO, (_, { enemy }) => { enemy.dead = true; hero.decrementLife(); if (isHeroDead()) { eventEmitter.emit(Messages.GAME_END_LOSS); return; // 遊戲失敗,提前結束 } if (isEnemiesDead()) { eventEmitter.emit(Messages.GAME_END_WIN); } }); eventEmitter.on(Messages.GAME_END_WIN, () => { endGame(true); }); eventEmitter.on(Messages.GAME_END_LOSS, () => { endGame(false); });
-
加入新的訊息。 新增這些訊息到 Messages 常數中:
GAME_END_LOSS: "GAME_END_LOSS", GAME_END_WIN: "GAME_END_WIN",
-
加入重新開始的功能 在按下特定按鈕後,程式會重新開始遊戲。
- 監聽
Enter
按鈕之按壓。 編輯視窗的 eventListener ,監聽按鍵的按壓:
else if(evt.key === "Enter") { eventEmitter.emit(Messages.KEY_EVENT_ENTER); }
-
加入重新遊戲的訊息。 加入這段訊息到 Messages 常數中:
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
- 監聽
-
制定遊戲規則。 編制下列的遊戲規則:
-
玩家勝利條件。 當所有敵軍艦艇被擊毀時,顯示勝利訊息。
- 首先,建立函式
displayMessage()
:
function displayMessage(message, color = "red") { ctx.font = "30px Arial"; ctx.fillStyle = color; ctx.textAlign = "center"; ctx.fillText(message, canvas.width / 2, canvas.height / 2); }
- 建立函式
endGame()
:
function endGame(win) { clearInterval(gameLoopId); // 設定延遲以確保所有圖像皆繪製完成 setTimeout(() => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); if (win) { displayMessage( "Victory!!! Pew Pew... - Press [Enter] to start a new game Captain Pew Pew", "green" ); } else { displayMessage( "You died !!! Press [Enter] to start a new game Captain Pew Pew" ); } }, 200) }
- 首先,建立函式
-
重新遊戲的邏輯。 當玩家損失所有的性命,或是贏下這場遊戲,顯示遊戲重來的提示。此外,在重新遊玩按鍵被按壓時,重新遊戲(你可以自己決定任一個鍵盤按鍵)。
- 建立函式
resetGame()
:
function resetGame() { if (gameLoopId) { clearInterval(gameLoopId); eventEmitter.clear(); initGame(); gameLoopId = setInterval(() => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); drawPoints(); drawLife(); updateGameObjects(); drawGameObjects(ctx); }, 100); } }
- 建立函式
-
在
initGame()
內呼叫eventEmitter
來重新設定遊戲:eventEmitter.on(Messages.KEY_EVENT_ENTER, () => { resetGame(); });
-
在 EventEmitter 加入函式
clear()
:clear() { this.listeners = {}; }
-
👽 💥 🚀 恭喜你,艦長!你的遊戲已經完成了!幹得好! 🚀 💥 👽
🚀 挑戰
加入遊戲音效!你能加入音效來提升遊戲品質嗎?或許在雷射擊中敵人,或是在英雄死亡、勝利時發出音效。看看這套沙盒,了解如何使用 JavaScript 播放音效。
課後測驗
複習與自學
你的功課是建立一款新的小遊戲。去探索一些有趣的遊戲,決定你想建造的遊戲類型。