收尾工作

这是 Gamedev Canvas 教程 的**第 10 步,也是最后一步**。您可以在 Gamedev-Canvas-workshop/lesson10.html 找到完成本课后代码应有的样子。

我们编写的任何游戏中总有改进的空间。例如,我们可以为玩家提供不止一条生命。他们可以犯一两个错误,仍然能够完成游戏。我们还可以改进代码渲染。

赋予玩家生命值

实现生命值非常简单。首先,让我们在声明其他变量的相同位置添加一个变量来存储生命值的数量

js
let lives = 3;

绘制生命值计数器与绘制得分计数器几乎相同——将以下函数添加到您的代码中,位于 drawScore() 函数下方

js
function drawLives() {
  ctx.font = "16px Arial";
  ctx.fillStyle = "#0095DD";
  ctx.fillText(`Lives: ${lives}`, canvas.width - 65, 20);
}

我们不会立即结束游戏,而是会减少生命值,直到它们不再可用。我们还可以重置球拍和球的位置,以便玩家从下一条生命开始。因此,在 draw() 函数中替换以下三行

js
alert("GAME OVER");
document.location.reload();
clearInterval(interval); // Needed for Chrome to end game

有了它,我们可以像下面给出的那样添加稍微复杂一点的逻辑

js
lives--;
if (!lives) {
  alert("GAME OVER");
  document.location.reload();
  clearInterval(interval); // Needed for Chrome to end game
} else {
  x = canvas.width / 2;
  y = canvas.height - 30;
  dx = 2;
  dy = -2;
  paddleX = (canvas.width - paddleWidth) / 2;
}

现在,当球击中屏幕底部边缘时,我们从 lives 变量中减去一条生命。如果没有剩余生命,则游戏失败;如果仍然有剩余生命,则球拍和球的位置将重置,球的移动也会重置。

渲染生命值显示

现在,您需要在 draw() 函数中添加对 drawLives() 的调用,并将其添加到 drawScore() 调用下方。

js
drawLives();

使用 requestAnimationFrame() 优化渲染

现在让我们处理一些与游戏机制无关,但与游戏渲染方式相关的事情。 requestAnimationFrame 可以帮助浏览器更好地渲染游戏,而不是我们目前使用 setInterval() 实现的固定帧率。替换以下行

js
interval = setInterval(draw, 10);

js
draw();

并删除每个实例

js
clearInterval(interval); // Needed for Chrome to end game

然后,在 draw() 函数的最底部(就在闭合花括号之前),添加以下行,这会导致 draw() 函数一遍又一遍地调用自身

js
requestAnimationFrame(draw);

draw() 函数现在在 requestAnimationFrame() 循环中被反复执行,但我们没有使用固定的 10 毫秒帧率,而是将帧率的控制权交还给浏览器。它将相应地同步帧率,并且仅在需要时渲染图形。与旧的 setInterval() 方法相比,这可以产生更高效、更流畅的动画循环。

对比您的代码

就这样——游戏的最终版本已经准备就绪,可以运行了!

注意:尝试更改生命值的数量以及球从球拍上弹出的角度。

游戏结束 - 暂时!

您已经完成了所有课程——恭喜!到目前为止,您应该已经了解了画布操作的基础知识以及 2D 游戏背后的逻辑。现在是时候学习一些框架并继续游戏开发了。您可以查看本系列的对应教程 使用 Phaser 开发 2D 打砖块游戏使用 Phaser 开发的 Cyber Orb 教程。您还可以浏览 MDN 上的游戏部分 以获取灵感和更多知识。

您也可以返回到 本教程系列的索引页。祝您编码愉快!