Collision with moving ball

In last chapter we looked how to check for collision between two balls and how to find new angle for movement after ball bounce. This was nice and easy, but it had problem: the balls can not move very fast or the collision detection fails. Here is an illustration of such situation:

In the picture ball1 (red) is at the position p0 and is moving with the speed v. In the end of movement cycle it will be at the position p1 (green). We have checked for collision with ball2 in last cycle and now we check for collision again after the movement. Because ball1 is far enough from ball2 both in start position and end position, we never detect collision with ball2. But we can see that actually there would be collision with ball2.

In this picture ball1 has collided with ball2 and the collision happens when it is at the position p3. We can calculate the position p3 using couple of vectors.

First we find vector between centers of both ball before movement:

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

Now we find point p2 which is the point in the movement vector closest to ball2. This point is easily found by projecting vector vc on the movement vector v. From point p2 we will draw vector to the center of ball2 (vn), this vector has same direction as normal for movement vector v.

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;

We can now check for length of vn against summed size of both balls. If vn is longer then both radiuses combined then there is no collision. If length of vn is equal to sizes then collision happens when ball1 is exactly at point p2. When vn is shorter, then collision happens before ball1 reaches p2.

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

Once we have detected collision between balls we should move ball1 back from point p2 to the point p3. But how to find p3? If you look again at the picture above about balls colliding you can probably see a triangle made from center of ball2, p2 and p3. We already know quite enough about that triangle, maybe not enough to fell in love with it, but enough to find p3. First, we know the lenght of side from p2 to center of ball2, this is our vector vn and length of vn is length of that side. Next we also know the length of side from p3 to center of ball2, this is equal to totalRadius. Now we can use good old Pythagoras theorem to find length of third side from p2 to 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};

So we move from p2 in opposite direction of movement vector v by the amount of moveBack. It is possible that p3 is outside of vector v meaning the collision will not happen during this movement cycle, but it might of happened in the past or might happen in the future. We only deal with collisions now so we have to check for p3 being on vector v:

if(game.v3.len<ob.len and dotP(game.v3, ob)>0){
  //collision
  game.ob1.p0=game.p3;
}

First, the length of vector from ball1 center to p3 has to be less then length of vector v. Also both vectors need to be in same direction, this can be found by calculating dot product between them.

This method expects that the balls are not colliding when movement starts, any such situation should be taken care before calculating collisions for this step.

I have made an example of ball with movement vector colliding with other ball:

You can drag the balls or endpoint of vector. Red circle is at ball1 starting point, green is where ball1 finishes, blue is ball2.

You can download the source fla of example here.

Next: 2 moving balls.

Top