#### Archived

This topic is now archived and is closed to further replies.

# Calculating the new direction after collision

This topic is 6196 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi! I previously asked about collision detection with lines and circles and I got it work. Thanks for help! Now I''d like to know how should I calculate the new direction after a collision with line or circle? I have following variables for the objects: double dMovX; double dMovY; I made it work so that if the object hits something when going to right I just multiply the dMovX with -1 so that it changes direction etc. But it doesn''t look realistic with lines.Could someone tell how to do this? At most I''m intrested in collision with circles and lines. Floru

##### Share on other sites
The way a collision causes an object to change it''s motion is through an impulse. This causes an instantaneous change in momentum, with the change given by the size and magnitude of the impulse. For a single moving object you can ignore the mass and work with velocity rather than momentum.

In practice this means you need to:
1) work out the direction of the collision. e.g. for a circle/ball hitting a line/surface without friction it will be the perpendicular/normal direction.
2) work out the impact speed, the speed in the direction of the collision, i.e. the speed towards the line/surface.
3) work out the impulse. If there''s no rotation it will be simply between 1 and 2 times the impact speed, with 1 being no bounce and 2 being maximum bounce. It is in the direction as the normal/perpendicular, away from the edge/surface.
4) Add it to the object velocity to get the velocity after the collision.

This is for an object hitting a fixed edge/surface, in 2D or 3D, ignoring friciton and rotation. These can be added in to the above proceedure but they make the calculations a lot more complex, especially in 3D.

##### Share on other sites
You need to find the surface normal, which is pretty much a line at 90 degrees to the point at which you are colliding with. Then, the angle between the ball''s original vector and the ball''s new vector are equal, but on opposite sides of the normal.

Trying is the first step towards failure.

##### Share on other sites

Thanks! But could you please give some kind of example because I''m not so good at maths? If lines are described with two points (x1,y1 and x2,y2) and I know when for example that a ball hits the line. And I know what is ball''s direction. And there is no need to calculate friction and rotation.

Floru

##### Share on other sites
One way is to reflect the component of the ball''s velocity in the direction of the normal to the line.

I.e:
Using (dMovX, dMovY) as the ball''s initial velocity, and points (x1,y1) and (x2,y2) as defining the line.

; Find line normal to line (as (nx, ny))
nx = y2 - y1 ; Find direction
ny = -(x2 - x1)
length = SquareRoot (nx*nx + ny*ny)
nx = nx / length ; Normalise (scale to length 1)
ny = ny / length
; Find component of ball''s velocity in direction of normal
dotProd = dMovX * nx + dMovY * ny
componentX = nx * dotProd
componentY = ny * dotProd
; Reflect this component of the ball''s velocity
newDMovX = dMovX - 2 * componentX
newDMovY = dMovY - 2 * componentY

This is off the top of my head, and hasn''t been tested.
I suggest looking up normals, vector normalization and dot product (or simply 2D vector arithmetic in general).

##### Share on other sites
I have some code for calculation the new directions.

// vDelta = Distance between the two actors:
float fContactAngle,
fXClosingVelocity, fYClosingVelocity, fResVelocity, fXContactVelocity,
fYContactVelocity, fClosingAngle, fMassFactor, fMass1, fMass2, fAdiff, fPortion;

// Determine the angle of contact
if(vDelta.fX != 0)
{
fContactAngle = (float) atan(vDelta.fY/vDelta.fX);
if(fContactAngle < 0)
fContactAngle = -fContactAngle;
}
else
fContactAngle = (float) PId2;

// To determine how the objects will rebound off of each
// other, we are not concerned with the speed of each
// object, but rather the relative, or closing, speeds
// of the two objects.
fXClosingVelocity = pActor2->vWorldVelocity.fX-pActor1->vWorldVelocity.fX;
fYClosingVelocity = pActor2->vWorldVelocity.fY-pActor1->vWorldVelocity.fY;
// Calculate the x & y speed in the direction of contact
fResVelocity = ASFastSqrt(fXClosingVelocity*fXClosingVelocity+fYClosingVelocity*fYClosingVelocity);
fXContactVelocity = (float) cos(fContactAngle)*fResVelocity;
fYContactVelocity = (float) sin(fContactAngle)*fResVelocity;

// Now, determine the closing angle.
if(fXClosingVelocity != 0)
{
fClosingAngle = (float) atan(fYClosingVelocity/fXClosingVelocity);
if(fClosingAngle < 0)
fClosingAngle = -fClosingAngle;
}
else
fClosingAngle = (float) PId2;

// Hmmmm...
// With equal masses,
// the max rebound speed is 1/2 the closing speed.
// With unequal masses,
// the max rebound speed is the closing speed.
// Okay then,
// Normalize the two masses to be: mass1 + mass2 = 2.0
fMassFactor = 2/(pActor1->fMass+pActor2->fMass);
fMass1 = pActor1->fMass*fMassFactor;
fMass2 = pActor2->fMass*fMassFactor;

if(pActor1->vWorldPos.fX > pActor2->vWorldPos.fX)
{
if(pActor1->vWorldPos.fY < pActor2->vWorldPos.fY)
{
// pActor1 is contacting upper right quadrant of pActor2
if(fYClosingVelocity < 0)
{
if(fXClosingVelocity < 0)
else
}
else
pActor1->vWorldVelocity.fX += fXContactVelocity*fPortion*fMass2;
pActor1->vWorldVelocity.fY -= fYContactVelocity*fPortion*fMass2;
pActor2->vWorldVelocity.fX -= fXContactVelocity*fPortion*fMass1;
pActor2->vWorldVelocity.fY += fYContactVelocity*fPortion*fMass1;
}
else
{
// pActor1 is contacting lower right quadrant of pActor2
if(fYClosingVelocity > 0)
{
if(fXClosingVelocity < 0)
else
}
else
pActor1->vWorldVelocity.fX += fXContactVelocity*fPortion*fMass2;
pActor1->vWorldVelocity.fY += fYContactVelocity*fPortion*fMass2;
pActor2->vWorldVelocity.fX -= fXContactVelocity*fPortion*fMass1;
pActor2->vWorldVelocity.fY -= fYContactVelocity*fPortion*fMass1;
}
}
else
{
if(pActor1->vWorldPos.fY < pActor2->vWorldPos.fY)
{
// pActor1 is contacting upper left quadrant of pActor2
if(fYClosingVelocity < 0)
{
if(fXClosingVelocity < 0)
else
}
else
pActor1->vWorldVelocity.fX -= fXContactVelocity*fPortion*fMass2;
pActor1->vWorldVelocity.fY -= fYContactVelocity*fPortion*fMass2;
pActor2->vWorldVelocity.fX += fXContactVelocity*fPortion*fMass1;
pActor2->vWorldVelocity.fY += fYContactVelocity*fPortion*fMass1;
}
else
{
// pActor1 is contacting lower left quadrant of pActor2
if(fYClosingVelocity > 0)
{
if(fXClosingVelocity < 0)
else
}
else
pActor1->vWorldVelocity.fX -= fXContactVelocity*fPortion*fMass2;
pActor1->vWorldVelocity.fY += fYContactVelocity*fPortion*fMass2;
pActor2->vWorldVelocity.fX += fXContactVelocity*fPortion*fMass1;
pActor2->vWorldVelocity.fY -= fYContactVelocity*fPortion*fMass1;
}
}

At the moment it only works for 2D. Could someone help me to add the third dimension??

##### Share on other sites
A realy simple technique,
which looks pretty good is to swap the velocity vectors of the colliding bodies.

//store the velocity of the first body in a seperate variable
velocity_body1 = intermediate_storage;

//set velocity body 1 = velocity of body 2
velocity_body1 = velocity_body2;

//set velocity of body 2 = velocity body 1 original value
velocity_body2 = intermediate_storage;

and you''ve swapped there velocity vectors!!
its not physically perfect, but its simple ao give it a shot

##### Share on other sites

Thanks for help!

I have now a working collision detection and I also know how to calculate new direction. I have a problem and I don''t know how common it is. I''ve seen demos where balls bounce in box or in area but sometimes the balls don''t work correctly. For example they stick into walls or go through them or bounce funny. I have same kind on problems. Rarely but I''d like to my system work perfectly. I also have a object which is controlled by the user (like in pinball game the flipper). But usually the balls go through. So how can I make my system perfect? Is this a common problem?

Floru

##### Share on other sites
I think the sticking-together problem is caused by the fact, that you only do coll-detection in finite time steps, i.e. you can only detect collisions if objects stick together already.
(Also if sometimes only a little bit)
I''ve had and still have some problems with that penetration problem, but you can solve it.
Try to find out "how much" the one object is inside the other one and then move your object away along the collision normal by your measured penetration. This will create a non-penetration state of the bodies.

A little bit hard to explain, but perhaps have a look into the FastCar source code.
http://www.oxforddynamics.co.uk

Ciao!
Roppi

http://www.moonbyte.de

##### Share on other sites

Thanks for the link but the documentation was quite complicated although the demo was quite impressive. Is there any simpler sample or documentation? I think some info how flipper games are made could also be useful. What about the sticking problem?

Floru

1. 1
2. 2
frob
16
3. 3
Rutin
12
4. 4
5. 5

• 13
• 12
• 59
• 14
• 15
• ### Forum Statistics

• Total Topics
632124
• Total Posts
3004243

×

## Important Information

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!