看一下第一行:function collisionCheck(object)
这是创建一个名为 collisionCheck 的函数。注意括号里的词 object,简单的说这就是一个“替代”变量。当我们稍后实际使用这个函数时需要用我们想要测试碰撞的对象名替换这个词。再往下看你会发现 object 这个词出现了很多次。一旦该函数执行,所有的 object 都会被替换为我们测试的实际对象名。
有没有觉得第二行很华丽?!
这一行的 if 语句检测了好几个条件。请注意我把每一块条件都放进了括号里,这样如此长的代码会容易阅读一些。
首先是检测是否 (Player.x + playerWidth > object.x)。一个图像的 x 值就是指该图像的左上角顶端的横坐标。碰撞的关键就是检测两个图像是否彼此有重叠,如果是则让他们停止重叠。那么为什么要在玩家的 x 值上再加上玩家的宽度呢?很简单,因为如果我们只检测玩家的 x 值,那么只有玩家图像的左上角顶端重叠了才会检测到碰撞。如果我们向右移动,而有一个方块挡在路上,我们需要碰撞在玩家图像的右侧边缘发生。玩家的 x 值加上其宽度就是该图像的右上角顶端的值。
简单来说,我们要做的就是在图像周围创建一个要求碰撞的盒型区域。一旦移动该盒型区域即为发生碰撞。
我画了几张图让你对这行代码有形象化的理解。蓝色方盒是个静止的方块,而那个绿色方盒就是玩家。黑线表明碰撞发生的地方。
到目前为止我们只是检测了玩家的右侧是否越过了其他物体的 x 坐标。
正如你看到的,现在我们的玩家处于碰撞区域中……但是我们还有更多的检测要做。下一个条件是 (Player.x < object.x + object.width)。
这个代码用于向左移动碰上物体图像右侧的时候。就是前一条件的反例而已。物体对象的 x 值加上它的宽度就是该物体的右侧。现在让我们看看前两个检查条件下的碰撞区域。
目前为止我们仍然处于碰撞区域。在设定了前两个条件之后,必须在这两条黑线之间碰撞才会发生。
下一个条件是 (Player.y + playerHeight > object.y)。
这是用于向下移动的时候。玩家的 y 坐标加上玩家的高度就是玩家图像的底端。如果该值大于其他物体的 y 坐标,则碰撞发生。让我们看看三个条件下的碰撞区域。
现在你会发现物体方块的上方已不再是碰撞区域,而玩家图像的底端必须大于物体方块图像的顶端才能使碰撞发生。
最后一个检查条件是 (Player.y < object.y + object.height)。
这部分代码用于检查向上移动。如果玩家的 y 坐标小于物体的底端(y 坐标加高度)则碰撞发生。这次我们使用“小于”是因为在屏幕上向上移动时 y 值是递减的。现在看看碰撞情况。
现在物体方块的底部以下也不是碰撞区域了。唯一会发生碰撞的地方就是方块所占据的区域。通过 if 语句的四个条件我们将方块所占区域包围了起来。
接着我们必须设定一旦进入该区域会发生什么,所以我们将玩家的 x 和 y 值设为 oldx 和 oldy。
此时我们尚未定义 oldx 和 oldy 的值。这是我们在主循环中要做的第一件事。这些值在每次循环开始时会被玩家当前的 x 和 y 值设定。如果我们的函数判断玩家处于碰撞区域则将玩家的位置设回上一次的位置,也就是 oldx 和 oldy 存储的值。这样我们就永远无法走进物体方块中了。函数在此结束。希望我上述的详细解析能帮到你理解这个函数。
最后就是我们的主循环。学到这你应该对下面的代码不难理解了。
代码:
while true do
-- store player's position at beginning of each loop
oldx = Player.x
oldy = Player.y
screen:clear()
movePlayer()
--check collision for each block