How to handle collision resolution in a top-down car game?

I have a top-down car game which takes place in an arena. The game is very very light on physics, so I'm not actually using a physics engine. The cars' movement is mostly managed by a struct I called Velocity, which stores a movement vector, an angle and speed. The speed will be mostly at the car's top speed, but there's acceleration involved to make reversing and going forwards again a bit smoother; the angle is increased or decreased depending on player input for turning; and then, the movement vector is updated with the new speed and angle values.

For collision detection, I've opted for SAT and as far as detection goes, it's working well. When it comes to resolution, however, I'm a bit at a loss. Out of the SAT implementation, I can get the MTV, but I feel it doesn't quite work with cars. I was thinking something in terms of maybe using the overlap value of the MTV (to acknowledge how strong was the hit) and the cars' movement vectors to define what's gonna happen to them, but I'm not coming up with anything.

(For completeness' sake, I'm using C++, Marmalade and IwGame, but I think the solution to this problem would be pretty much platform independent.)

Any ideas? Thanks!

• I do realize there are pretty complete (and complex) solutions, such as this one, but it's a bit of an overkill for my scope, specially considering a short deadline I'm working with. What I'm looking for doesn't need to be realistic, it's can be something simple, as long as it's fun :) Dec 26 '12 at 19:36

So, after a few trips to the Physics section of Khan Academy for a refresher on momentum and some more research, I've found this series of articles on the matter:

(These articles originally have a linearity to them, and there's more articles in between those listed above in the series, but those that I listed are the ones that relate to the problem at hand.)

The solution above deals with the scenario of balls colliding, so it isn't exactly perfect for cars, but I've found a decent way around that: I store the resulting velocity from the collision in a different vector than the velocity vector from the car. Then, the car will follow the direction of the of both the collision vector and the velocity vector. Just so there's some actual change to the velocity vector after the collision, I use the projection of the collision vector onto the velocity vector as the resulting velocity of the car.

Here's the bulk of the resulting code:

// Get the normal vector from lhs->rhs
CIwFVec2 normalAB = other->getPosition() - this->getPosition();
normalAB.Normalise();

// Rotate 90° to get the tangential
CIwFVec2 tangenAB = CVector2Util::getLeftNormal(normalAB);

// The vectors in the normal and tangential direction will act as axes

// Calculate the initial velocity in N (normalAB)
float lhsIniVelN = this->movementModule.getVelocityVector().Dot(normalAB);
float rhsIniVelN =  rhs->movementModule.getVelocityVector().Dot(normalAB);

// Calculate the initial velocity in T, which will also
// be the final velocity in T
float lhsVelT = this->movementModule.getVelocityVector().Dot(tangenAB);
float rhsVelT =  rhs->movementModule.getVelocityVector().Dot(tangenAB);

// Get the masses
float mLhs = TEMP_ARBITRARY_MASS;
float mRhs = TEMP_ARBITRARY_MASS;

// Get the final velocities in N
float lhsFinVelN = (mRhs * rhsIniVelN * (C_E + 1) + lhsIniVelN * (mLhs - C_E * mRhs)) / (mLhs + mRhs);
float rhsFinVelN = (mLhs * lhsIniVelN * (C_E + 1) + lhsIniVelN * (mLhs - C_E * mRhs)) / (mLhs + mRhs);

// Finally, translate the final velocities in N-T to X-Y
CIwFVec2 lhsFinalVel;
CIwFVec2 rhsFinalVel;

// This can be done with the dot product of the final velocities
// in N and T with normalAB and tangenAB, respectively
lhsFinalVel.x = lhsFinVelN * normalAB.x + lhsVelT * tangenAB.x;
lhsFinalVel.y = lhsFinVelN * normalAB.y + lhsVelT * tangenAB.y;
rhsFinalVel.x = rhsFinVelN * normalAB.x + rhsVelT * tangenAB.x;
rhsFinalVel.y = rhsFinVelN * normalAB.y + rhsVelT * tangenAB.y;

// Pass the final velocities to the movement module
this->movementModule.resolveCollision(lhsFinalVel);
rhs->movementModule.resolveCollision(rhsFinalVel);
• It's also worth noting that having a physics engine would probably save a lot of hassle from this kind of problem, although I wouldn't have learned half as much, I'd say. So to anyone who might have this kind of problem: weigh your options well :) Jan 2 '13 at 18:14