Circle Collision Response
Hi,
I am workin on my air hockey project for school. For the collision between the paddle and the puck, I use distance formula. If the distance is less than the sum of radii then they have collided. For the response part, I resolve the velocity along and perpendicular to the line joining the centres. Then I reverse the direction of the puck''s velocity along the line joining the two and then re-resolve the velocities into the x and y components respectively. When I calculated I ended up with some complex formula :
(btw, paddle does not move after collision).
float m = (puck.y - active_paddle.y) / (puck.x - active_paddle.x);
float theta = atan(m);
float ct = cos(theta);
float st = sin(theta);
float r1 = (puck.vx * ct) + (puck.vy * st);
float r2 = (puck.vy * ct) - (puck.vx * st);
puck.vx = r1*ct + r2*st;
puck.vy = r1*st - r2*ct;
puck.vx and vy are the final x and y components of velocities. For some strange reason this whole thing just dies.. it goes through many times, etc, etc.
PLS HELP! I need to submit my project in 3 days.
Thanks,
Rohit.
Hmm..
If by ''dies'' you mean crashes you are doing a divide without checking to see if you are dividing by zero. Dealing with divide by zero is difficult here as it arises quite normally: better to avoid to altogether by usin atan2, e.g.
float theta = atan2((puck.y - active_paddle.y), (puck.x - active_paddle.x);
You could still have problems if puck and active_paddle are the same in x AND y. In this case just pick an arbitrary angle, as any direction will move them apart.
float theta = atan2((puck.y - active_paddle.y), (puck.x - active_paddle.x);
You could still have problems if puck and active_paddle are the same in x AND y. In this case just pick an arbitrary angle, as any direction will move them apart.
John BlackburneProgrammer, The Pitbull Syndicate
Ok my mistake.. by dies I mean the collision doesn''t work properly as in there is something wrong with the logic.. It goes through and stuff.. It''s not a divide by zero.
Thanks,
Rohit.
Thanks,
Rohit.
Hmm..
Looking at your code there are a couple of other things of note. First you don''t need to use angle at all: instead you can just calculate your direction vector,
[dx]
[dy]
directly:
float dx = active_paddle.y - puck.y;
float dy = active_paddle.x - puck.x;
float length = sqrt(dx * dx + dy * dy);
if (length == 0) {
// pick some direction
dx = 0;
dy = 1;
}
else
{
dx /= length;
dy /= length;
}
dx and dy are equivalent to your ct and st, but this way it''s more obvious that they form a vector along the line from the puck to the paddle.
Then you don''t seem to be calculating the ''bounce'' properly: it''s difficult to say where your going wrong as what you''ve got doesn''t correspond to anything I''m familiar with. Instead this should work:
//calculate the speed of the puck towards the paddle
float speed = puck.vx * dx + puck.vy * dy;
// make sure it is going towards paddle
if (speed > 0)
{
// bounce vector = speed * direction * (1 + e) is
// added to the puck''s velocity.
// ''e'' is the coefficient of restitution, a number
// between 0 and 1 which gives the amount of bounce,
// where 0 gives no bounce and 1 gives maximum, e.g.
// perfectly elastic, collision.
puck.vx -= speed * dx * (1 + e);
puck.vy -= speed * dy * (1 + e);
}
[dx]
[dy]
directly:
float dx = active_paddle.y - puck.y;
float dy = active_paddle.x - puck.x;
float length = sqrt(dx * dx + dy * dy);
if (length == 0) {
// pick some direction
dx = 0;
dy = 1;
}
else
{
dx /= length;
dy /= length;
}
dx and dy are equivalent to your ct and st, but this way it''s more obvious that they form a vector along the line from the puck to the paddle.
Then you don''t seem to be calculating the ''bounce'' properly: it''s difficult to say where your going wrong as what you''ve got doesn''t correspond to anything I''m familiar with. Instead this should work:
//calculate the speed of the puck towards the paddle
float speed = puck.vx * dx + puck.vy * dy;
// make sure it is going towards paddle
if (speed > 0)
{
// bounce vector = speed * direction * (1 + e) is
// added to the puck''s velocity.
// ''e'' is the coefficient of restitution, a number
// between 0 and 1 which gives the amount of bounce,
// where 0 gives no bounce and 1 gives maximum, e.g.
// perfectly elastic, collision.
puck.vx -= speed * dx * (1 + e);
puck.vy -= speed * dy * (1 + e);
}
John BlackburneProgrammer, The Pitbull Syndicate
January 02, 2003 10:56 AM
Hi,
Thanks a lot. But I think you''ve made a mistake.. what you''re doing is saying that the force acts along the line joining the 2 centres. That is true, so I think the stuff should be resolved. I can''t really get ur logic. Anyways, it also bombed.. as in the collisions were no where near accurate.. Any further suggestions ?
Thanks,
Rohit
Thanks a lot. But I think you''ve made a mistake.. what you''re doing is saying that the force acts along the line joining the 2 centres. That is true, so I think the stuff should be resolved. I can''t really get ur logic. Anyways, it also bombed.. as in the collisions were no where near accurate.. Any further suggestions ?
Thanks,
Rohit
What do you mean ''nowhere near accurate'' ? It''s difficult to know what your problem is without a better description of it.
I''ve looked over it and can''t see a mistake in my last post, either in the code or comments, though I can''t easily test the code myself to see what it''s doing.
Note you have to initialise e to some sensible value, e.g.
float e = 0.5;
It''s intended that the impulse (not force) acts along the line joining the centres, which is about how it works in the tabletop air-hockey games I''ve played: real/ice hockey would be much more complex with the shape of the stick head being important.
Also make sure they only hit once. If you''re not careful you can do to collisions in short succession that cancel each other out. The line
if (speed > 0)
should avoid this in most cases but you might still want to add a further check.
Also this does not take account of the speed of the paddle, if any, so it will always lose speed in a collision as it''s not given a push by the paddle. To add in the paddle speed change this line
float speed = puck.vx * dx + puck.vy * dy;
to something like
float speed = (puck.vx - active_paddle.vx) * dx + (puck.vy - active_paddle.vy) * dy;
I''ve looked over it and can''t see a mistake in my last post, either in the code or comments, though I can''t easily test the code myself to see what it''s doing.
Note you have to initialise e to some sensible value, e.g.
float e = 0.5;
It''s intended that the impulse (not force) acts along the line joining the centres, which is about how it works in the tabletop air-hockey games I''ve played: real/ice hockey would be much more complex with the shape of the stick head being important.
Also make sure they only hit once. If you''re not careful you can do to collisions in short succession that cancel each other out. The line
if (speed > 0)
should avoid this in most cases but you might still want to add a further check.
Also this does not take account of the speed of the paddle, if any, so it will always lose speed in a collision as it''s not given a push by the paddle. To add in the paddle speed change this line
float speed = puck.vx * dx + puck.vy * dy;
to something like
float speed = (puck.vx - active_paddle.vx) * dx + (puck.vy - active_paddle.vy) * dy;
John BlackburneProgrammer, The Pitbull Syndicate
can i send it 2 u and u can see for urself y its not accurate ?
Btw, I''m studyin for IIT and all, I know quite a bit about e and all that stuff..Just not able 2 implement it.
Thanks,
Rohit.
Btw, I''m studyin for IIT and all, I know quite a bit about e and all that stuff..Just not able 2 implement it.
Thanks,
Rohit.
Hmm..
> can i send it 2 u and u can see for urself y its not accurate ?
Better to describe what you''re seeing here. Quicker and easier for me, and you''ll benefit from the knowledge and experience of the many other visitors to this forum.
Better to describe what you''re seeing here. Quicker and easier for me, and you''ll benefit from the knowledge and experience of the many other visitors to this forum.
John BlackburneProgrammer, The Pitbull Syndicate
OKay.. but it''s hard to describe. Basically, sometimes it goes right through. Then when it starts movin in wrong directions. and don''t u think it should be puck.vx = -(...) rather than puck.vx -= ...
So basically the collision response is going quite crazy. My logic for this whole collision thing was to resole the velocities along and perpendicular to the line joining the centres and then to invert the velocity along that line. It would be something like reflection off the tangent.. But that''s not working out..Any suggestions ?
Thanks,
Rohit.
So basically the collision response is going quite crazy. My logic for this whole collision thing was to resole the velocities along and perpendicular to the line joining the centres and then to invert the velocity along that line. It would be something like reflection off the tangent.. But that''s not working out..Any suggestions ?
Thanks,
Rohit.
Hmm..
> Basically, sometimes it goes right through.
That sounds like it''s missing collisions or mis-interpreting them.
Make sure you are doing the calculations often enough that you don''t miss collisions: you can add a breakpoint or have it print a message whenever they are close enough to collide. The precise condition is
if (length < puck.radius + active_paddle.radius)
so check you are testing this or something equivalent to it.
Also the test
if (speed > 0)
determines whether they are moving towards each other and only changes the velocity if they are. If you take it out it will also detect situations where the puck has already moved through the paddle before you do the calculations. But if you do this you''ll have to make sure you don''t do multiple bounces per collision.
Also make sure you test all things that could collide, e.g. if there are multiple paddles check them all. It''s not clear whether you are doing this.
> Then when it starts movin in wrong directions. and don''t u
> think it should be puck.vx = -(...) rather than puck.vx -= ...
It''s like that as it''s based on the laws of physics and is more realistic. There are other ways of doing it, but as they''re not based on real physics in such cases you have to decide your own rules, and whether they are ''correct'' is far more subjective.
That sounds like it''s missing collisions or mis-interpreting them.
Make sure you are doing the calculations often enough that you don''t miss collisions: you can add a breakpoint or have it print a message whenever they are close enough to collide. The precise condition is
if (length < puck.radius + active_paddle.radius)
so check you are testing this or something equivalent to it.
Also the test
if (speed > 0)
determines whether they are moving towards each other and only changes the velocity if they are. If you take it out it will also detect situations where the puck has already moved through the paddle before you do the calculations. But if you do this you''ll have to make sure you don''t do multiple bounces per collision.
Also make sure you test all things that could collide, e.g. if there are multiple paddles check them all. It''s not clear whether you are doing this.
> Then when it starts movin in wrong directions. and don''t u
> think it should be puck.vx = -(...) rather than puck.vx -= ...
It''s like that as it''s based on the laws of physics and is more realistic. There are other ways of doing it, but as they''re not based on real physics in such cases you have to decide your own rules, and whether they are ''correct'' is far more subjective.
John BlackburneProgrammer, The Pitbull Syndicate
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement