views:

109

answers:

4

Hi, this is a Math problem for a 2d game.

Given 2 object ( 2 car, 2 tank, 2...), for each object i know: 
1. X, Y 
2. Actual Speed
3. Degree of movement (or radiant)

How to calculate the "effect" of a collision for the 2 object

Ps:

I "move" the object with this simple formula each tick of my "game loop":

ychange = Math.Sin(radiant) * ((carspeed / xVar));
xchange = Math.Cos(radiant) * ((carspeed / xVar));

(where xVar is a "multiplicator" to make more slow my car on the screen)

And for the "first" object which collide, if i add a "minus" (-) in front of that formula, i can simulate a good "bounce" of the first object.. but not for the second.

So my question regard a way to calculate a good (not perfect ! ) and more realistic "impact effect" for the second object.

Thanks for your help

A: 

Hmmm...it's been a long time since I've done game development collisions so take my advice lightly. Have you tried "flipping" the degree of movement or simply adding one Pi to radiant?

Aaron Hathaway
+3  A: 

The simplest way is to have them swap velocities. This makes sense if they are identical.

If you want to do more, you can choose a random value for a parameter that will determine whether they have a glancing collision (barely touching) or a full impact, or something in between. You can also simulate different masses of the two objects (when a motorcycle hits a freight truck, not much happens to the truck). Finally, you can have a collision that is only partly elastic; that is, they do not bounce like rubber balls, they crunch and lose some energy. These will require some math, and an understanding of the physics.

Beta
That is only going to work if they collide in such a way that the centres move through each other. Which in real life is practically never going to happen. Imagine a glancing blow. That would come out all wrong.
Ohmu
@Ohmu: It's true that swapping velocities is realistic only for a perfect dead-center collision of identical objects, but it's a good (not perfect!) and *simple* trick to use in a game. And notice that I did mention more realistic treatments including "glancing collisions".
Beta
+3  A: 

Few months ago I implemented a Snooker game. I used the following code to make two balls collide. Note that they are not bounding boxes.

This method computes the resulting speed and angles based on the mass, speed and angle of each objects.

It worked like a charm at my game.

 float   dx = b1->x - b2->x, dy = b1->y - b2->y;
    float   d = sqrt(sqr(dx) + sqr(dy));
    float   vp1, vp2, vx1, vx2, vy1, vy2;
    vx1 = ballSpeedX(b1);
    vx2 = ballSpeedX(b2);
    vy1 = ballSpeedY(b1);
    vy2 = ballSpeedY(b2);
    vp1 = vx1 * dx / d + vy1 * dy / d;
    vp2 = vx2 * dx / d + vy2 * dy / d;

    float   distance = sqrt(sqr(dx) + sqr(dy));

//  Unit vector in the direction of the collision.
    float   ax = dx / distance, ay = dy / distance;

//  Projection of the velocities in these axes.
    float   va1 = vx1 * ax + vy1 * ay, vb1 = -vx1 * ay + vy1 * ax;
    float   va2 = vx2 * ax + vy2 * ay, vb2 = -vx2 * ay + vy2 * ax;

//  New velocities in these axes (after collision): edmass / b2->mass);
    float   vaP2 = va2 + (1.0 + D_BALL_ELASTIC_COEFFICIENT) * (va1 - va2) / (1.0 + b2->mass / b1->mass);

//  Undo the projections.
    vx1 = vaP1 * ax - vb1 * ay; vy1 = vaP1 * ay + vb1 * ax; // new vx,vy for ball 1 after collision.
    vx2 = vaP2 * ax - vb2 * ay; vy2 = vaP2 * ay + vb2 * ax; // new vx,vy for ball 2 after collision.

    b1->speed = sqrt(sqr(vx1) + sqr(vy1));
    b1->angle = acos(fabs(vx1 / b1->speed));

    b2->speed = sqrt(sqr(vx2) + sqr(vy2));
    b2->angle = acos(fabs(vx2 / b2->speed));

This code was written in pure C. The way I store the movement data is just the same as yours. The variables b1 and b2 are balls.

I believe the code itself isn't hard to understand, but the physic isn't trivial.

Hope it helps!

Vinícius Gobbo A. de Oliveira
+1  A: 

Here is an explanation of the physics:

You have four unknows: The x and y velocities of each ball after the collision.

So you need four equations.

Conservation of momentum in x and y gives two. Mom = mv
Conservation of kinetic energy gives a third; Ke = 1/2 * mv^2 (before & after)

Further to this, the principle of relativity can be used to assume one ball is initially stationary, say uB.x = uB.y = 0

And the impulse must happen along the line that joins between the centres of each ball, at the time of impact. So if you assumed ball B was initially at rest, now it will be moving in the direction of that line, so you can express vB.y = f + g * vB.x, thus reducing the number of unknowns to 3.

Three unknowns, three equations. Yay!

If the collision is not elastic, then it depends how accurately you want to simulate. Something like Ke_after = 0.99 * Ke_before, and then throw that into the math.

I leave it as an exercise to the reader to derive the full equations.

Ohmu
If you want to do the physics right, it's *much* easier to use the center-of-mass frame.
Beta