Physics Math for 2D Games
The math side a this simple 2D physics is sum what complicated, first off you'll need an understanding of linear algebra and a little bit of Linear Calculus (integration method). These help make the a simple physics quite nicely. For this example you'll only need to have a Vector2 implementations which I've give it to you here.gmath.h
typedef float real;
#define REAL_MAX FLT_MAX
// Math function wrapper
#define real_sqrt sqrt
#define real_pow pow
// Basic Vector2 object
struct Vec2 {
real x, y;
Vec2() : x(0), y(0) {}
Vec2(real x, real y) : x(x), y(y) {}
// Operators
Vec2 operator -() { // makes a vec2 negitive
return Vec2(-x, -y);
}
Vec2 operator + (const Vec2& v) {
return Vec2(x+v.x, y+v.y);
}
Vec2 operator - (const Vec2& v) {
return Vec2(x-v.x, y-v.y);
}
Vec2 operator * (const real r) {
return Vec2(x*r, y*r);
}
void operator = (const Vec2& v) {
x = v.x;
y = v.y;
}
void operator += (const Vec2& v) {
x += v.x;
y += v.y;
}
void operator -= (const Vec2& v) {
x -= v.x;
y -= v.y;
}
void operator *= (const real& r) {
x *= r;
y *= r;
}
real dot(Vec2& v) {
return x*v.x+y*v.y;
}
real magnitude() {
return real_sqrt(x*x+y*y);
}
real magnitudeSquare() {
return x*x+y*y;
}
void normalize() {
real dist = magnitude();
*this *= ((real)1)/dist;
}
// utility function
void clear() {
x = y = 0;
}
};
This is a really this is all that you need. I'm also use my own typedef for float called "real" because if I want switch to double float point I can do that later.
Collision Object (For Now)
Now that we have a simple Vec2 object we can now create the collision object, the collision object is used to moving a character around the screen or make an obstacle that will get in the way of a character. Here's the header version of the Collision Object (Physics Object).colobj.h
struct ColObj {
Vec2 pos; // Position
Vec2 vel; // Velocity
Vec2 acc; // Acceleration
real damper; // Dampaning
real inverseMass; // Inverse Mass
Vec2 force; // Forces Accumilator
// setters and getters
void setPos(const Vec2& v);
Vec2 getPos();
void setVel(const Vec2& v);
Vec2 getVel();
void setAcc(const Vec2& v);
Vec2 getAcc();
void setDamping(real d);
real getDamping();
void setMass(real mass);
real getMass();
void clearForces();
void addForce(const Vec2& v);
void intergration(real time);
};
This will be the main object to use for collisions, I'm going to put other types of data such as shape id and user data via void* pointer later. Now let me explain the 6 fields I'm using. Which are pos, vel, acc, damper, inverseMass, and forces. Pos which is position is the locations of the ColObject, Vel is the velocity this is the direction of the object, and Acc which is acceleration of the object.Damper is a real value that prevents the object from sliding. If the value is low then it will stop quicker, if the value is high than it will take time to slow down. If the value is 1.0 it will continuously slide forever. The mass of the object is how dense it is, if the value is higher than the object will need some momentum to move if lower the object will move reletively quickly. If the mass is zero then it won't move at all. Forces are values that changes the object, this could be gravity, wind velocity, or some other force in the world.
Most the methods in this are actually setters and getters, but for exception of setMass, getMass, clearForces, addForce, and integration. setMass and getMass internally is converting the value to its inverse.
colman.cpp
void ColObj::setMass(real mass) {
if(mass == 0) {
this->inverseMass = mass;
} else {
this->inverseMass = ((real)1.0)/mass;
}
}
real ColObj::getMass() {
if(inverseMass == 0) {
return REAL_MAX;
} else {
return ((real)1.0)/inverseMass;
}
}
When you set a mass it it will convert the mass into the inverse mass of the object, and if you want to get the mass it will convert it back to it. The next one is forces, there are current two methods.
colobj.cpp
void ColObj::clearForces() {
force.clear();
}
void ColObj::addForce(const Vec2& v) {
force += v;
}
Clear forces is self explanatory it simply makes the force field back to zero value, the addForce method however modifies the force field (lol pun). And the next one integration method, this contains math algorithm to help solve the physics program, the integration I'm using here is a simple Euler Integration. I know it isn't perfect but I don't care for now, I can always use Varlet or RK4 later on.
colobj.cpp
void ColObj::intergration(real time) {
assert(time > 0.0);
this->pos += vel * time;
Vec2 racc = acc;
racc += force * inverseMass;
vel += racc * time;
vel *= real_pow(damper, time);
clearForces();
}
This is what I've been working on for the 2 days since I've been on summer break, and its been really fun. If you want a really good source for Game Physics, than go out and buy a book called "Game Physics Engine Development" by Ian Millington. This book will help you understand how Physics Engines work by building a simple one that can be used for a 3D game. If you are interested than here a link Game Physics Engine Development at Amazon.com. I'll post the next one pretty soon so take care. (Note: I'll post the source code up under an once I get done with these set of articles).