球和线
到现在你可能已经厌倦了总是只有一个移动的点。倒不是说点本身有什么不好,它们是好的,但是毕竟,点只是点。你能在你的周围能看到多少个点?我相信不会很多。最后,我们将向前迈进一大步,开始移动一些更加真实的东东西 – 球。
我相信你在生活中看到过很多的球,所以你知道他们和点有什么不同。球是有宽度的。在我们的2D例子中,球是用圆来表示的,它有圆心坐标并且有半径。
game.myOb={r:10};
game.myOb.p0={x:150, y:100};
已知一个运动的球的半径是10,另外我们知道球的中心坐标,它的移动向量和半径,我们要计算球撞上墙壁的会在哪儿。

图中,灰色的圈圈表示球的中心与墙壁的交点。事实上球在更早的时候就碰到墙壁了。球碰到墙壁的时候,球的位置应该这样的,将墙壁向量(green)向它的法线方向移动一个半径的距离,然后求出这个新的向量和球的运动向量(红色)的交点。所以,我们可以不使用墙壁向量,而是用一个方向相同,起点位置不同的向量。
Axes method
球和线的交点也可以用别的方法来计算。下面就来研究下如何通过一些简单的投影来确定球是否与墙壁碰撞。

图中,我们可以看到,球处于他的运动向量的终点p1处。我们绘制一个蓝色的向量,从墙壁向量的起点(v2.p0)出发,到达球的中心。现在我们将这个新的向量在墙壁的法线上进行投影,得到向量v3(红色)。为了将球紧贴墙壁放置,我需要将它向墙壁的法线方向移动:
ball.r-v3.len
在示例代码中,我们计算出墙壁法线的单位向量:
v.lx = v.dy; v.ly = -v.dx;
在runme函数里,我们检查所有的墙壁:
for(var i=1; i<5; i++){
var w=game["v"+i];
//if we have hit the wall
var pen=ob.r-findIntersection(ob, w);
if(pen>=0){
//move object away from the wall
ob.p1.x+=w.lx*pen;
ob.p1.y+=w.ly*pen;
//change movement
var vb=bounce(ob, w);
ob.vx=vb.vx;
ob.vy=vb.vy;
}
}
对于每一个墙壁,如果球撞进去了,我们就计算出撞进去的距离,再将球拉回来,然后用之前同样的方法去计算反弹之后的向量。
计算撞进去的距离的函数:
function findIntersection(v1, v2){
//vector between center of ball
//and starting point of wall
var v3={};
v3.vx=v1.p1.x-v2.p0.x;
v3.vy=v1.p1.y-v2.p0.y;
//project this vector on the normal of the wall
var v=projectVector(v3, v2.lx, v2.ly);
//find length of projection
v.len=Math.sqrt(v.vx*v.vx+v.vy*v.vy);
return v.len;
}
在这个例子中,尝试拖动墙壁四个角的点:
注意,这个例子并没有考虑墙壁的长度,所有的墙壁都被认为是无限长的。这种方式可以用来保证球在盒子里面,而不会出去。在下一章节里面,我们会研究如何处理球和墙壁的角的碰撞。
你可以下载fla源文件。

Post a Comment