桨和键盘控制
这是 Gamedev Canvas 教程 中 10 个步骤中的第 4 步。您可以从 Gamedev-Canvas-workshop/lesson4.html 中找到完成本课后代码的正确示例。
球在墙上自由弹跳,您可以无限期地观看它,但目前没有交互性。如果您无法控制它,那就不是游戏!因此,让我们添加一些用户交互:一个可控的桨。
定义一个用来击打球的桨
所以,我们需要一个桨来击打球。让我们为它定义一些变量。将以下变量添加到代码顶部,在其他变量旁边
const paddleHeight = 10;
const paddleWidth = 75;
let paddleX = (canvas.width - paddleWidth) / 2;
这里我们定义了桨的高度和宽度,以及它在 x
轴上的起始点,用于后面的代码计算。让我们创建一个函数,在屏幕上绘制桨。将以下代码添加到 drawBall()
函数下方
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
允许用户控制桨
我们可以将桨绘制在任何我们想要的地方,但它应该响应用户的操作。现在是实现一些键盘控制的时候了。我们需要以下内容
- 两个变量用于存储关于是否按下了左右控制按钮的信息。
- 两个用于
keydown
和keyup
事件的事件监听器。当按钮被按下时,我们想要运行一些代码来处理桨的移动。 - 两个处理
keydown
和keyup
事件的函数,即按下按钮时将运行的代码。 - 能够将桨向左和向右移动
可以使用布尔变量定义和初始化已按下的按钮,例如示例中的情况。将这些行添加到变量组附近
let rightPressed = false;
let leftPressed = false;
两者的默认值为 false
,因为一开始没有按下控制按钮。为了监听按键,我们将设置两个事件监听器。将以下代码行添加到 JavaScript 底部的 setInterval()
行上方
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
当键盘上的任何键触发 keydown
事件(当按下键时)时,keyDownHandler()
函数将被执行。第二个监听器也遵循相同的模式:keyup
事件将触发 keyUpHandler()
函数(当键停止被按下时)。现在将这些添加到您的代码中,位于 addEventListener()
行下方
function keyDownHandler(e) {
if (e.key === "Right" || e.key === "ArrowRight") {
rightPressed = true;
} else if (e.key === "Left" || e.key === "ArrowLeft") {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (e.key === "Right" || e.key === "ArrowRight") {
rightPressed = false;
} else if (e.key === "Left" || e.key === "ArrowLeft") {
leftPressed = false;
}
}
当我们按下某个键时,此信息将存储在一个变量中。每种情况下的相关变量都被设置为 true
。当释放键时,变量被重置为 false
。
这两个函数都将事件作为参数,由 e
变量表示。您可以从中获取有用的信息:key
包含有关被按下的键的信息。大多数浏览器使用 ArrowRight
和 ArrowLeft
表示左右方向键,但我们需要包含 Right
和 Left
检查来支持 IE/Edge 浏览器。如果按下了左方向键,则 leftPressed
变量将设置为 true
,当释放左方向键时,leftPressed
变量将设置为 false
。相同的模式适用于右方向键和 rightPressed
变量。
桨移动逻辑
我们现在已经设置了用于存储关于已按下键的信息的变量、事件监听器和相关函数。接下来,我们将进入代码,使用我们刚刚设置的所有东西,并在屏幕上移动桨。在 draw()
函数内,我们将在渲染每一帧时检查是否按下了左右方向键。我们的代码可能看起来像这样
if (rightPressed) {
paddleX += 7;
} else if (leftPressed) {
paddleX -= 7;
}
如果按下了左方向键,桨将向左移动 7 个像素,如果按下了右方向键,桨将向右移动 7 个像素。这目前有效,但是如果我们长时间按住任一方向键,桨会从画布边缘消失。我们可以通过更改代码来改进这一点,只在画布边界内移动桨,如下所示
if (rightPressed) {
paddleX = Math.min(paddleX + 7, canvas.width - paddleWidth);
} else if (leftPressed) {
paddleX = Math.max(paddleX - 7, 0);
}
我们使用的 paddleX
位置将在画布左侧的 0
和右侧的 canvas.width-paddleWidth
之间移动,这将完全按照我们的预期工作。
将上述代码块添加到 draw()
函数的底部,就在结束的大括号上方。
现在唯一剩下要做的就是从 draw()
函数中调用 drawPaddle()
函数,以便将它实际打印到屏幕上。将以下代码行添加到 draw()
函数中,就在调用 drawBall()
的代码行下方
drawPaddle();
比较您的代码
查看您的代码与下面的实时示例相比如何
注意:尝试让桨移动得更快或更慢,或者改变它的尺寸。