7.9 KiB
构建太空游戏第六部分:结束与重启
课前测验
在游戏中,有多种方式来表达结束条件。作为游戏的创作者,你需要决定游戏为何结束。以下是一些可能的原因,假设我们正在讨论你目前正在构建的太空游戏:
- 摧毁了
N
艘敌方飞船:如果你将游戏分为不同的关卡,那么通常需要摧毁N
艘敌方飞船才能完成一个关卡。 - 你的飞船被摧毁:有些游戏中,如果你的飞船被摧毁,你就会输掉游戏。另一种常见的方法是引入“生命”的概念。每次飞船被摧毁时,扣除一条生命。当所有生命耗尽时,游戏结束。
- 收集了
N
分:另一种常见的结束条件是收集一定的分数。如何获得分数取决于你,但通常会为各种活动分配分数,比如摧毁敌方飞船,或者收集敌方飞船被摧毁后掉落的物品。 - 完成一个关卡:这可能涉及多个条件,比如摧毁
X
艘敌方飞船、收集Y
分,或者收集某个特定的物品。
重启
如果玩家喜欢你的游戏,他们可能会想要重新玩一次。当游戏因某种原因结束时,你应该提供一个重启的选项。
✅ 想一想,在什么条件下你认为游戏会结束,然后玩家会如何被提示重启。
要构建的内容
你需要为游戏添加以下规则:
- 赢得游戏。当所有敌方飞船被摧毁时,玩家赢得游戏。此外,显示某种胜利信息。
- 重启。当所有生命耗尽或游戏胜利时,你应该提供一种方式来重启游戏。记住!你需要重新初始化游戏,并清除之前的游戏状态。
推荐步骤
找到在your-work
子文件夹中为你创建的文件。它应该包含以下内容:
-| assets
-| enemyShip.png
-| player.png
-| laserRed.png
-| life.png
-| index.html
-| app.js
-| package.json
通过输入以下命令启动你的项目:
cd your-work
npm start
上述命令将在地址http://localhost:5000
上启动一个HTTP服务器。打开浏览器并输入该地址。你的游戏应该处于可玩的状态。
提示:为了避免在Visual Studio Code中出现警告,编辑
window.onload
函数,使其直接调用gameLoopId
(不使用let
),并在文件顶部独立声明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; // loss before victory } if (isEnemiesDead()) { eventEmitter.emit(Messages.GAME_END_WIN); } }); eventEmitter.on(Messages.GAME_END_WIN, () => { endGame(true); }); eventEmitter.on(Messages.GAME_END_LOSS, () => { endGame(false); });
-
添加新的消息类型。将这些消息添加到常量对象中:
GAME_END_LOSS: "GAME_END_LOSS", GAME_END_WIN: "GAME_END_WIN",
-
添加重启代码,以便在按下选定按钮时重启游戏。
- 监听按键
Enter
。编辑窗口的事件监听器以监听该按键:
else if(evt.key === "Enter") { eventEmitter.emit(Messages.KEY_EVENT_ENTER); }
-
添加重启消息。将此消息添加到你的消息常量中:
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); // set a delay so we are sure any paints have finished 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 = {}; }
- 创建
-
👽 💥 🚀 恭喜你,船长!你的游戏完成了!干得好!🚀 💥 👽
🚀 挑战
添加一个音效!你能为游戏添加音效以增强游戏体验吗?比如在激光命中、英雄飞船死亡或胜利时播放音效?查看这个sandbox来学习如何使用JavaScript播放音效。
课后测验
复习与自学
你的任务是创建一个全新的样本游戏,因此探索一些有趣的游戏,看看你可能会构建哪种类型的游戏。
作业
免责声明:
本文档使用AI翻译服务Co-op Translator进行翻译。尽管我们努力确保准确性,但请注意,自动翻译可能包含错误或不准确之处。应以原始语言的文档作为权威来源。对于关键信息,建议使用专业人工翻译。因使用本翻译而引起的任何误解或误读,我们概不负责。