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/zh/6-space-game/6-end-condition/README.md

8.0 KiB

构建太空游戏第六部分:结束与重启

课前测验

课前测验

在游戏中有多种方式可以表达“结束条件”。作为游戏的创作者,你可以决定游戏为何结束。以下是一些可能的原因,假设我们正在讨论你迄今为止构建的太空游戏:

  • 摧毁了N艘敌方飞船:如果游戏分为不同的关卡,通常需要摧毁N艘敌方飞船才能完成一个关卡。
  • 你的飞船被摧毁:有些游戏中,如果你的飞船被摧毁,你就会输掉游戏。另一种常见的方式是引入“生命值”的概念。每次飞船被摧毁都会扣除一条生命值,当所有生命值耗尽时,游戏结束。
  • 收集了N:另一种常见的结束条件是收集一定的分数。如何获得分数取决于你,但通常会为各种活动分配分数,比如摧毁敌方飞船或收集敌方飞船被摧毁后掉落的物品。
  • 完成一个关卡:这可能涉及多个条件,比如摧毁X艘敌方飞船、收集Y分,或者收集特定的物品。

重启

如果玩家喜欢你的游戏,他们可能会想要重新玩一次。当游戏因某种原因结束时,你应该提供一个重启的选项。

思考一下你认为游戏在什么条件下会结束,以及如何提示玩家重启游戏。

要构建的内容

你将为游戏添加以下规则:

  1. 赢得游戏。当所有敌方飞船被摧毁时,玩家赢得游戏。此外,显示某种胜利信息。
  2. 重启。当所有生命值耗尽或游戏获胜时,你应该提供一种方式来重启游戏。记住!你需要重新初始化游戏,并清除之前的游戏状态。

推荐步骤

找到在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),并在文件顶部独立声明gameLoopIdlet gameLoopId;

添加代码

  1. 跟踪结束条件。添加代码以跟踪敌方飞船数量,或者英雄飞船是否被摧毁,方法是添加以下两个函数:

    function isHeroDead() {
      return hero.life <= 0;
    }
    
    function isEnemiesDead() {
      const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead);
      return enemies.length === 0;
    }
    
  2. 添加逻辑到消息处理器。编辑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);
    });
    
  3. 添加新的消息类型。将以下消息添加到常量对象中:

    GAME_END_LOSS: "GAME_END_LOSS",
    GAME_END_WIN: "GAME_END_WIN",
    
  4. 添加重启代码。编写代码以在按下选定按钮时重启游戏。

    1. 监听按键Enter。编辑窗口的事件监听器以监听此按键:
     else if(evt.key === "Enter") {
        eventEmitter.emit(Messages.KEY_EVENT_ENTER);
      }
    
    1. 添加重启消息。将以下消息添加到你的消息常量中:

      KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
      
  5. 实现游戏规则。实现以下游戏规则:

    1. 玩家胜利条件。当所有敌方飞船被摧毁时,显示胜利信息。

      1. 首先,创建一个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);
      }
      
      1. 创建一个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)  
      }
      
    2. 重启逻辑。当所有生命值耗尽或玩家赢得游戏时,显示游戏可以重启。此外,当按下“重启”键时重启游戏(你可以决定哪个键映射到重启)。

      1. 创建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);
        }
      }
      
    3. initGame()中调用eventEmitter以重置游戏:

      eventEmitter.on(Messages.KEY_EVENT_ENTER, () => {
        resetGame();
      });
      
    4. 为EventEmitter添加一个clear()函数:

      clear() {
        this.listeners = {};
      }
      

👽 💥 🚀 恭喜你,舰长!你的游戏已经完成!干得好! 🚀 💥 👽


🚀 挑战

添加音效!你能为游戏添加音效以增强游戏体验吗?比如激光击中、英雄飞船被摧毁或赢得游戏时的音效?查看这个sandbox学习如何使用JavaScript播放音效。

课后测验

课后测验

复习与自学

你的任务是创建一个全新的样本游戏,因此可以探索一些有趣的游戏,看看你可能会构建什么类型的游戏。

作业

构建一个样本游戏

免责声明
本文档使用AI翻译服务 Co-op Translator 进行翻译。尽管我们努力确保翻译的准确性,但请注意,自动翻译可能包含错误或不准确之处。应以原文档的原始语言版本为权威来源。对于关键信息,建议使用专业人工翻译。我们对因使用此翻译而引起的任何误解或误读不承担责任。