Skip to content

Flash向量-10-高速运动的球

在上一节里面,我们学会了如何检测2个球的碰撞,和如何找到碰撞后的运动方向。看起来非常既好用,又简单,但是其实是有问题的:球不能运动的太快,否者碰撞检测会失效。以下是这种情形的一个说明:

速度过快,碰撞检测失效

图中,球1(红色)位于p0,以速度v移动。在下一个运动周期里面,它会到达p1的位置(绿色)。我们在上一个周期和本次的周期都会检测球1和球2是否发生碰撞。由于不论是在起点还是在终点,球1和球2的距离足够的大,我们检测不到球1和球2的碰撞。但是从图中可以看出,事实上球1和球2确实发生了碰撞。

上图中,球1和球2会在位置p3发生碰撞。可以这样来计算p3:

首先我们找到移动之前2个球的中心连线的向量:

vc={};
vc.p0=ball1.p0;
vc.p1=ball2.p0;

现在,我们计算出p2,它是运动向量上与球2距离最小的点。这个点很容易找到,只需要将向量vc在运动向量上进行投影,如果你已经不记得如何计算投影,可以在基础知识章节中查找。

我们绘制一个向量vn,从点p2到球2的中心点。这个向量和运动向量的法线方向相同。

vp=projectVector(vc, v.dx, v.dy);
p2={x:v.p0.x+vp.vx, y:v.p0.y+vp.vy};
vn={};
vn.p0=p2;
vn.p1=ball2.p0;

现在,我们可以比较这个向量的长度和两个球的半径之和。如果vn比半径之和大,那么不会发生碰撞。如果vn的长度和半径之和相等,那么刚好插肩而过。如果vn的长度小于半径之和,那么碰撞在到达p2这一点之前发生了。

totalRadius=ball1.r+ball2.r;
var diff=totalRadius-vn.len;
if(diff>0){
  //collision
}else{
  //no collision
}

当检测到球发生了碰撞,应该将球1从点p2移回点p3。但是怎么计算p3呢?如果你仔细看看上面的图片,很可能会发现,球2的中心点,p2和p3构成了一个三角形。我们对三角形非常的熟悉了,虽然还不足以让我们爱上她,但是已经足以让我们找到p3。首先,我们知道点p2到球心的长度,也就是向量vn的长度。然后,我们可以求得点p3到球2中心的长度,等于球的半径之和。现在,就可以使用古老而好用的勾股定理,来计算第三边(从p2到p3)的长度。

moveBack=Math.sqrt(totalRadius*totalRadius-vn.len*vn.len);
p3={x:p2.x-moveBack*v.dx, y:p2.y-moveBack*v.dy};
v3={p0:v.p0, p1:p3};

所以,我们将运动向量v从p2反向移动moveBack这么长的距离。有可能p3在向量v的外面,此时意味着碰撞不在本次运动循环中发生,但是但是有可能是在过去或者未来发生。我们只处理此刻的碰撞,我们要求p3必须落在向量v上面:

if(game.v3.len0){
  //collision
  game.ob1.p0=game.p3;
}

首先,从球1中心到p3的长度必须小于向量v的长度。同时2个向量必须放心相同,这一点可以通过计算点乘来确定。

这种检测方法的前提是,球在最开始的时候没有发生碰撞,如果遇到这种情况的话,在计算碰撞之前要小心哦。

我制作了一个例子,运动的球碰撞其他的球:

你可以拖动那些球,也可以拖动运动向量的终点。红色的圆代表球1的开始运动的时候,绿色是球1的运动完成的时候,蓝色是球2。

你可以下载fla源文件

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*