I'm working on the physics for my GTA2-like game so I can learn more about game physics.
The collision detection and resolution are working great.
I'm now just unsure how to compute the force to apply to a body after it collides with a wall.
My rigid body looks like this:
/our simulation object
class RigidBody extends Entity
{
//linear
private Vector2D velocity = new Vector2D();
private Vector2D forces = new Vector2D();
private float mass;
private Vector2D v = new Vector2D();
//angular
private float angularVelocity;
private float torque;
private float inertia;
//graphical
private Vector2D halfSize = new Vector2D();
private Bitmap image;
private Matrix mat = new Matrix();
private float[] Vector2Ds = new float[2];
private Vector2D tangent = new Vector2D();
private static Vector2D worldRelVec = new Vector2D();
private static Vector2D relWorldVec = new Vector2D();
private static Vector2D pointVelVec = new Vector2D();
private static Vector2D acceleration = new Vector2D();
public RigidBody()
{
//set these defaults so we don't get divide by zeros
mass = 1.0f;
inertia = 1.0f;
setLayer(LAYER_OBJECTS);
}
protected void rectChanged()
{
if(getWorld() != null)
{
getWorld().updateDynamic(this);
}
}
//intialize out parameters
public void initialize(Vector2D halfSize, float mass, Bitmap bitmap)
{
//store physical parameters
this.halfSize = halfSize;
this.mass = mass;
image = bitmap;
inertia = (1.0f / 20.0f) * (halfSize.x * halfSize.x) * (halfSize.y * halfSize.y) * mass;
RectF rect = new RectF();
float scalar = 10.0f;
rect.left = (int)-halfSize.x * scalar;
rect.top = (int)-halfSize.y * scalar;
rect.right = rect.left + (int)(halfSize.x * 2.0f * scalar);
rect.bottom = rect.top + (int)(halfSize.y * 2.0f * scalar);
setRect(rect);
}
public void setLocation(Vector2D position, float angle)
{
getRect().set(position.x,position.y, getWidth(), getHeight(), angle);
rectChanged();
}
public Vector2D getPosition()
{
return getRect().getCenter();
}
@Override
public void update(float timeStep)
{
doUpdate(timeStep);
}
public void doUpdate(float timeStep)
{
//integrate physics
//linear
acceleration.x = forces.x / mass;
acceleration.y = forces.y / mass;
velocity.x += (acceleration.x * timeStep);
velocity.y += (acceleration.y * timeStep);
//velocity = Vector2D.add(velocity, Vector2D.scalarMultiply(acceleration, timeStep));
Vector2D c = getRect().getCenter();
v.x = getRect().getCenter().getX() + (velocity.x * timeStep);
v.y = getRect().getCenter().getY() + (velocity.y * timeStep);
setCenter(v.x, v.y);
forces.x = 0; //clear forces
forces.y = 0;
//angular
float angAcc = torque / inertia;
angularVelocity += angAcc * timeStep;
setAngle(getAngle() + angularVelocity * timeStep);
torque = 0; //clear torque
}
//take a relative Vector2D and make it a world Vector2D
public Vector2D relativeToWorld(Vector2D relative)
{
mat.reset();
Vector2Ds[0] = relative.x;
Vector2Ds[1] = relative.y;
mat.postRotate(JMath.radToDeg(getAngle()));
mat.mapVectors(Vector2Ds);
relWorldVec.x = Vector2Ds[0];
relWorldVec.y = Vector2Ds[1];
return relWorldVec;
}
//take a world Vector2D and make it a relative Vector2D
public Vector2D worldToRelative(Vector2D world)
{
mat.reset();
Vector2Ds[0] = world.x;
Vector2Ds[1] = world.y;
mat.postRotate(JMath.radToDeg(-getAngle()));
mat.mapVectors(Vector2Ds);
worldRelVec.x = Vector2Ds[0];
worldRelVec.y = Vector2Ds[1];
return worldRelVec;
}
//velocity of a point on body
public Vector2D pointVelocity(Vector2D worldOffset)
{
tangent.x = -worldOffset.y;
tangent.y = worldOffset.x;
pointVelVec.x = (tangent.x * angularVelocity) + velocity.x;
pointVelVec.y = (tangent.y * angularVelocity) + velocity.y;
return pointVelVec;
}
public void applyForce(Vector2D worldForce, Vector2D worldOffset)
{
//add linear force
forces.x += worldForce.x;
forces.y += worldForce.y;
//add associated torque
torque += Vector2D.cross(worldOffset, worldForce);
}
@Override
public void draw( GraphicsContext c)
{
c.drawRotatedScaledBitmap(image, getPosition().x, getPosition().y,
getWidth(), getHeight(), getAngle());
}
public Vector2D getVelocity()
{
return velocity;
}
public void setVelocity(Vector2D velocity)
{
this.velocity = velocity;
}
}
The way it is given force is by the applyForce method, this method considers angular torque.
I'm just not sure how to come up with the vectors in the case where:
RigidBody hits static entity
RigidBody hits other RigidBody that may or may not be in motion.
Would anyone know a way (without too complex math) that I could figure out the opposite force I need to apply to the car?
I know the normal it is colliding with and how deep it collided.
My main goal is so that say I hit a building from the side, well the car should not just stay there, it should slowly rotate out of it if I'm more than 45 degrees. Right now when I hit a wall I only change the velocity directly which does not consider angular force.
Thanks!