本篇是 Gamedev Canvas tutorial 10节教程中的第三节。如果你完成了本篇教程之后,你可以从 Gamedev-Canvas-workshop/lesson3.html 看到源码。

看到我们的球动起来很惊讶吧,但是它很快就从屏幕上消失了,当然我们是可以控制它的。我们会实现一些非常简单的碰撞检测(详细后面解释),使球在画布的四周反弹回来。

简单的碰撞

我们将检查球体是否与边缘接触,如果有接触我们将相应的改变它的运动方向。

为了运算方便我们定义一个名为 ballRadius 的变量,来存储球的半径。向代码中添加一下内容:

var ballRadius = 10;

现在更新绘制球的 drawBall() 函数:

ctx.arc(x, y, ballRadius, 0, Math.PI*2);

从顶部和底部弹起

有四面墙壁可以让它反弹回来,我们先来看上面的那面墙。我们需要判断球运动的每一帧,球体是否与画布的顶部边缘接触。如果有接触,我们将会改变球体的运动方向,使它向相反的方向移动,并保证它在画布的可见范围之内。记住坐标系统的左上角,让我们开始并加以下代码:

if(y + dy < 0) {
    dy = -dy;
}

如果球的纵坐标(y轴)值小于零,我们将在球体原有的运动方向上逆转。如果球体向上移动的速度是2像素/帧,现在就是向上移动速度是-2像素。这相当于此时向下移动的速度是2像素/帧。

上面的代码将处理球与画布顶部边缘的反射,现在让我们思考一下底部边缘如何处理:

if(y + dy > canvas.height) {
    dy = -dy;
}

如果球的y位置大于canvas的高度(记住,我们从左上角计算y值,所以顶部边缘从0开始,底部边缘在480像素),然后通过像以前那样反转y轴运动而离开底部边缘。

我们可以将这两句冗长的代码合二为一:

if(y + dy > canvas.height || y + dy < 0) {
    dy = -dy;
}

如果其中一个判断为 true, 则反转球的运动。

从左边和右边反弹

我们有顶部和底部的边缘,所以我们来考虑一下左边和右边的边缘。 实际上非常相似,你所要做的就是颠倒x而不是y:

if(x + dx > canvas.width || x + dx < 0) {
    dx = -dx;
}

if(y + dy > canvas.height || y + dy < 0) {
    dy = -dy;
}

你应该把上面的代码块插入到draw()函数中,就在大括号之前。

球部分消失在墙上!

测试你的代码,你会看到我们的球碰到任一边缘都会反弹!然而,我们还发现了一个问题,当球碰撞到边缘,反弹之前:

这是因为我们正在计算墙和球的中心碰撞点,而我们应该围绕它的周长来做。 如果碰到墙壁,球应该会弹起来,而不是陷入墙壁一半时,所以让我们来调整一下我们的判断条件。 更新你之前添加的代码:

if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
    dx = -dx;
}
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
    dy = -dy;
}

当球的中心到墙的边缘之间的距离与球的半径完全相同时,它将改变运动的方向。

比较你的代码

让我们再次检查这个部分的代码与你之间有何差异:

练习: 尝试修改你的代码,在每次碰到墙壁时都要把球的颜色改成随机的颜色。

下一步

现在我们已经到了我们的球正在移动和留在游戏板上的阶段。 在第四章中,我们将看看如何实现一个可控制的paddle - 参见paddle和键盘控制

文档标签和贡献者

此页面的贡献者: wbamberg, xrr2016, varcat, jackblackevo, jiii
最后编辑者: wbamberg,