#ifndef PHYSICS_HH
#define PHYSICS_HH
#include "Vector.hh"
#include <vector>
#include <queue>
#include <ClanLib/core.h>
typedef uint16_t TimeMS;
const TimeMS PHYSICS_TICK_MS = 10;
enum TerrainType {EMPTY, DIRT, ROCK};
const Vector DIRECTIONS[] = { Vector(0,-1), Vector(1,-1), Vector(1,0), Vector(1,1),
Vector(0,1), Vector(-1,1), Vector(-1,0), Vector(-1,-1) };
// forward-declare
class PhysicsObject;
typedef Vector Force;
struct Derivative;
class PhysicsWorld {
friend class PhysicsObject;
private:
CL_Timer tick_timer;
uint32_t tick_counter;
protected:
std::vector<PhysicsObject*> objects;
Vector gravity;
Vector dimensions;
std::vector<std::vector<TerrainType> > terrain;
CL_SlotContainer slots;
PhysicsWorld (Vector gravity, Vector dimensions);
public:
void addObject (PhysicsObject *object);
void tick (void);
uint32_t getTick (void);
void generateTerrain (int seed);
bool collided (Vector oldPos, Vector newPos);
Vector getNormal(Vector hitPoint, Vector prevPoint);
TerrainType getType(Vector pos) const;
};
class PhysicsObject {
protected:
PhysicsWorld &world;
float mass;
Vector position;
Vector velocity;
// Whether the object (worms mainly) is in the air
// or firmly on the ground. Affects to physics.
bool inAir;
// Shape of the object. We use a polygon with 4 edges
// to make easy to draw with Clanlib. The coordinates
// are relative to the center point.
std::vector<Vector> shape;
// Force queue that is emptied on every tick
std::queue<Force> forceq;
Vector posAfterTick;
Vector velAfterTick;
/**
* @param shape Corners of the four sided polygon.
*/
PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity);
/**
* Used to handle in-air movement
*/
virtual void applyForce (Force force, TimeMS dt);
/**
* Called on network clients to sync state from server
*/
void updatePhysics (Vector position, Vector velocity);
/**
* Handle ground movement
*
* @return new position
*/
Vector walk (bool right);
/**
* Handle ground-jumping
*/
void jump (void);
/**
* Handle ground-bounce
*/
void bounce (Vector normal);
private:
void updatePosition (void);
bool possibleLocation (Vector loc);
/**
* Use RK4 to integrate the effects of force over a time intervall.
*/
void integrate(Force force, TimeMS dt);
Derivative evaluate(Force force, TimeMS dt, Derivative &d);
Vector acceleration(const Force &force);
public:
Vector getPosition (void);
std::vector<Vector>& getShape(void);
void setShape (std::vector<Vector> shape);
void tick (void);
};
struct Derivative {
Vector dx; // Velocity
Vector dv; // Acceleration
};
#endif