不是所有的墙壁都会无限延伸,他们通常从某处出发,然后在某处结束。我们把这称为起点和终点。现在我要计算球与墙壁的角碰撞时的位置点和碰撞后的运动向量。
红色的是墙壁向量,灰色的是球的运动向量,可能碰到墙壁,也可能碰到墙角。在findIntersection函数里面,我们检测到距离球最近的墙壁,并找到让球“从相交状态回到紧贴状态的那个向量”。
墙壁向量为v2,球的运动向量是v1。先找到从墙壁的起点到球的中心的向量v3:
v3.vx=v1.p1.x-v2.p0.x; v3.vy=v1.p1.y-v2.p0.y;
然后计算v3和墙壁向量v2的点乘:
var dp=v3.vx*v2.dx + v3.vy*v2.dy;
如果点乘为负数的话,说明球离墙壁的起点很近。并且那个移动回去的向量是向量v3。
if(dp<0){
var v=v3;
}
如果点乘是0,或者正数,我就检测球是不是和墙壁的终点很近。所以,首先,找到墙壁的终点到球中心的向量:
else{
var v4={};
v4.vx=v1.p1.x-v2.p1.x;
v4.vy=v1.p1.y-v2.p1.y;
并且和第一个点类似,我们可以再次计向量算v4和墙壁的点乘。
var dp=v4.vx*v2.dx + v4.vy*v2.dy;
如果点乘是正数,球会碰到终点,而v4是用于将球移开:
if(dp>0){
var v=v4;
}
然而,如果这个时候,点乘为0或者负数,那么墙壁的边缘和球很近。此时,我们从墙壁起点到球中心的向量v3在墙壁法线上进行投影。球将会从墙壁法线方向移动回去,就像上一节一样。
else{
var v=projectVector(v3, v2.lx, v2.ly);
}
最后我们返回当前的向量。
return v;
记住球的反弹向量将和球的返回向量垂直。当球碰到墙壁的时候,我们可以用墙壁向量来计算新的移动向量。当球碰到墙角的时候,从墙壁的终点到球中心的向量的法线就可以派上用场了。
尝试拖动墙壁试一试,观察球与墙壁的碰撞。
因为我们只检测了球的运动向量的终点,所以当球的速度非常快的时候,有可能球会穿过墙壁。为了避免这种情况,你应该确保球的速度永远不会超过它的半径。

Post a Comment