views:

135

answers:

4

The balls are defined as a circles with a radius, a position and a velocity, which is a 2D vector. The walls are defined by a start point and end point.

I am able to detect the collision between the ball and the wall and know how to reflect it about the normal. However the same collision can be detected AGAIN and the change of direction is repeatedly flipped, meaning essentially the ball stops moving.

So really need a simple way to say that a ball is moving away from the line already so I can ignore any additional collisions.

A: 

Maybe not the best way but you could place the ball very small away from wall...otherwise I think it would be good to know more about your design...

Flo
+3  A: 

You need to have a normal vector on the wall to know its orientation. Take a dot product between the ball velocity vector and the wall normal. If the result of the dot product is greater than zero, the ball is moving away from the wall. If it is zero, then the ball is moving parallel and if it is less than zero, then the ball is moving towards the wall.

Additional explanation: 2010-08-29 18:17

A question has come up about the case of when the wall supports collisions from both sides. To handle collisions properly, you have to answer two questions: which side of the wall is the ball currently on ('inside' or 'outside') and which way is it moving relative to the wall normal? How to determine the answer to the second question is answered above.

To answer the question about whether the ball is 'inside' or 'outside' of the wall, you start by calculating the vector from the ball to the wall (a point on the wall - center of the ball). Take the dot product of that vector with the wall normal vector. If the result is less than zero then the ball is 'outside' the wall. Equal to zero is on the wall and greater than zero is 'inside' the wall.

You then have the answer to your two questions. Is the ball currently 'inside' or 'outside' the wall and is it currently moving towards the 'inside' or 'outside' of the wall.

Hitesh
+1  A: 

Hitesh's answer is actually wrong, as the normal of the line could point in either direction perpendicular to the line. It is how i first thought to solve the problem, but then quickly realised would not work.

Balls: xb, yb, radius, vx, vy

Walls: x1, y1, x2, y2

float Ang1 = atan2(y1-yb, x1-xb);
float Ang2 = atan2(y2-yb, x2-xb);
float AngB = atan2(vy, vx);

//Catch cases where the wall straddles the change from 2pi radians to 0 radians
//and revolve all the angles around by pi to avoid the problem
//Can only happen in a specific region, this can be done easily by adding 2pi to
// any negative angles.

Ang1 = (Ang1 < 0) ? Ang1 + 2 *PI : Ang1;
Ang2 = (Ang2 < 0) ? Ang2 + 2 *PI : Ang2;
AngB = (AngB < 0) ? AngB + 2 *PI : AngB;

AngU = max(Ang1, Ang2);
AngL = min(Ang1, Ang2);

bool Towards = (AngL < AngB && AngB < AngU) ? true : false;
will
If the normal of the nearest wall face points away from the ball, the ball is inside of the wall. Also, be aware that arctan() isn't unique in all quadrants.
David Lively
@David Lively: He defines each wall just using two points though, so each wall is really just a line, with no depth, and hence no definition of "inside the wall".Also, the arctan() not being unique is the reason i used atan2; http://en.wikipedia.org/wiki/Atan2
will
A: 

Just a thought.. If you know that the ball already hit the wall - how about using some kind of a flag that says so. Once you detect collision - set this flag to true. More specifically - if you have some walls, and balls cannot collide with one another - add an array of booleans to each ball which represent weather or not it collided with each wall. Initialize it to all false. Once you detect collision - set the value of the coresponding wall to true, and so you'll know not to look for the same ball's collision with the same wall. Once you detect that ball collides with another wall - set all values of the array to false, except for the last wall that was collided with. Obviously a ball cannot collide with the same wall twice before hitting another wall (again, assuming walls are straight, balls do not collide with each other, and that balls are going in straight directions.. not assuming those require a bit more work :))

Is that what you were looking for or did I not get your question?

Oren A
I thought about doing that, and it would no doubt work, but it seemed cleaner, to do the check for moving apart.
davidbuttar