Repositioning circles on collision

Started by
5 comments, last by thestien 11 years, 11 months ago
Hey, I'm trying to make an asteroids clone an I'm wandering how to reposition circles when they collide.
It would be easy to just do velocity = -velocity but the objects move fast so when the collide they get pretty far into each other so when they try to rebound it just gets stuck...

Here's the formula for what I did before (doesn't work very well):
diff = pos2 - pos1
if(pos1 < pos2){
pos1 = pos1 + ((diff - r)/2)
pos2 = pos2 - ((dif - r)/2)
}else if(pos2 > pos1){
pos1 = pos1 + ((diff + r)/2)
pos2 = pos2 - ((dif + r)/2)
}

pos1 is the position of one circle
pos2 is the position of another circle
diff is the difference between positions
r is the radius
it divides by 2 to space them equally.

When I try this in my project it doesn't work. Both the circles move with each other in a weird vibrating motion...
Any help will get +1 rep thanks!
Advertisement
Inverting velocity (preferably only along the normal component) works just fine if you first check whether they are actually moving towards each other.

Edit: also your code has "pos2<pos2" in the second if...
Thanks but I wont be keeping the rebound as inverting the velocity.
I will be doing energy transference which can make a small object moving incredible fast, collide with a big circle (getting pretty far into the circle) and rebound to a really slow speed which will make the program keep thinking there is a collision.

Equation for the energy transference:
Velocity1 = (Velocity2 * Mass2)/Mass1;
where 1 means first circle (entity).
and 2 means the second circle (entity).
Back to your original code:

diff = pos2 - pos2
if(pos1 < pos2){
pos1 = pos1 + ((diff - r)/2)
pos2 = pos2 - ((diff - r)/2)
}else if(pos2 > pos1){
pos1 = pos1 + ((diff + r)/2)
pos2 = pos2 - ((diff + r)/2)
}

Is that the actual code from the program or did you rewrite this in the browser? you calculate diff as pos2-pos2 which is always 0 then pos1<pos2 doesn't make sense for 2d vectors/positions to begin with. Is r the radius of a single circle? In that case the "penetration" is 2*r-diff and the position updates should read "pos1 += (2*r-diff)/2" etc. (never 2*r+diff tough, you are inverting the wrong sign in the second part of the if)
Okay, it's easy to determine how far to move them back so they're just touching; if the radiuses of the two circles are r1 and r2, the centres should be r1+r2 apart. You can break the relative motion into two components; towards each other and at right angles. The component towards each other should be reversed and the other component can probably stay the same. If you know the component towards each other and how far they interpenetrated you could even estimate when they should have made contact, and calculate where they should go next.

Back to your original code:

diff = pos2 - pos2
if(pos1 < pos2){
pos1 = pos1 + ((diff - r)/2)
pos2 = pos2 - ((diff - r)/2)
}else if(pos2 > pos1){
pos1 = pos1 + ((diff + r)/2)
pos2 = pos2 - ((diff + r)/2)
}

Is that the actual code from the program or did you rewrite this in the browser? you calculate diff as pos2-pos2 which is always 0 then pos1<pos2 doesn't make sense for 2d vectors/positions to begin with. Is r the radius of a single circle? In that case the "penetration" is 2*r-diff and the position updates should read "pos1 += (2*r-diff)/2" etc. (never 2*r+diff tough, you are inverting the wrong sign in the second part of the if)


No the code is just written into the browser (badly).
The reason it does /2 is so the circles move an equal distance instead of just one circle moving and making the collision look a bit weird in the program.
At the moment both the radiuses are the same so I haven't put any support for different sizes.
I wrote the code into the browser because if it were actual code it would be a bit longer (for both x and y axis).

Heres the actual code at the moment:

int diffx = ent.x - x;
int diffy = ent.y - y;

int p1x = x,p1y = y;
int p2x = ent.x, p2y = ent.y;

if(x < ent.x){
int am = (diffx - circularRadius)/2;
p1x = x + am;
p2x = ent.x - am;
}else if(x > ent.x){
int am = (diffx + circularRadius)/2;
p1x = x + am;
p2x = ent.x - am;
}


if(y < ent.y){
int am = (diffy - circularRadius)/2;
p1y = y + am;
p2y = ent.y - am;
}else if(y > ent.y){
int am = (diffy + circularRadius)/2;
p1y = y + am;
p2y = ent.y - am;
}
x = p1x;
y = p1y;
ent.x = p2x;
ent.y = p2y;


rebound(ent);


ent is the Entity that the circle is colliding with.
Hi

Maybe you should check for collision if there is move them back so that they are now on the bounds of the collision and then change there velocity that should stop them getting stuck inside each other.

oops i think i misread the question.

so move the centre of the colliding circle back along the direction of travel -x, -y, by the amount of distance between the two radius of both circles. then handle the colision

This topic is closed to new replies.

Advertisement