#ifndef PHYSICS_OBJECT_HH
#define PHYSICS_OBJECT_HH
#include <ClanLib/display.h>
// Forward declares
class PhysicsObject;
struct Derivative;
#include "PhysicsWorld.hh"
#include "Vector.hh"
#include "Timer.hh"
#include "Config.hh"
// Type definitions
typedef Vector Force;
/**
* PhysicObject class. A basic PhysicsObject class.
*/
class PhysicsObject {
protected:
// This probably shouldn't be done this way.
Vector position;
Vector velocity;
float mass;
bool inAir; // Is the object "on the ground"
float collision_elasticity;
// Attributes for players
float aim; // Aim direction (half circle)
bool facingRight; // Player facing
PhysicsObject(PhysicsWorld &world, float mass, Vector position,
Vector velocity);
~PhysicsObject() {}
/**
* Add force to the force queue to be applied on next tick.
*
* @param force Force vector
*/
void applyForce(Force force);
/**
* Change player aim
*
* @param da Aim angle change
*/
void changeAim(float da);
/**
* Set player facing.
*
* @param facingRight True if player is facing right.
*/
void setFacing(bool facingRight);
/**
* Makes the player jump in the air.
* @param direction -1: jump left, 0: jump up, 1: jump right
*/
void jump(int direction);
/**
* Handle ground-bounce
*
* @param normal Normal vector relative to which to bounce
*/
void bounce(Vector normal);
/**
* Called on network clients to sync state from server
*
* @param position New position
* @param velocity New velocity
* @param inAir New inAir value
* @param facingRight New facingRight value
* @param aim New aim
*/
virtual void updatePhysics(Vector position, Vector velocity, bool inAir, bool facingRight, float aim);
private:
// TODO: I'd be tempted to use some already made ClanLib structure
// here.
// Shape of the object. Edge points of the shape polygon.
std::vector<Vector> shape;
// TODO: Should these operations be moved to PhysicsWorld?
// Force queue that is emptied on every tick
std::queue<Force> forceq;
/**
* Handle player movement and apply forces.
*/
void updatePosition(TimeMS dt);
// TODO: Should these be moved to PhysicsWorld?
/**
* Use RK4 to integrate the effects of force over a time interwall.
*
* @param force Force to integrate
* @param dt Time intervall
*/
void integrate(Force force, TimeMS dt, Vector &posAfterTick, Vector &velAfterTick);
/**
* Evaluate the value of the derivative at given time
*
* @param force Force
* @param dt Time
* @param d Previous derivative
*/
Derivative evaluate(Force force, TimeMS dt, Derivative &d, const Vector &posAfterTick, const Vector &velAfterTick);
/**
* Return object acceleration with given force.
*
* @param force Force
* @return Acceleration
*/
Vector acceleration(const Force &force);
// TODO: If integration is moved to PhysicsWorld then this should
// also move there.
/**
* Handle ground movement.
*
* @param right Boolean describing the movement direction.
* @return New position
*/
void walk(TimeMS, bool right);
Vector walk_one_step(float, bool);
/*
* Handle collision. TODO: This is not used. It probably should
* be?
*/
virtual void onCollision() {}
/*
* TODO: This probably does some kind of collision
* detection. Could be named/documented better.
*/
bool possibleLocation(Vector loc);
public:
PhysicsWorld &world;
/**
* Get current object position.
*
* @return Position vector
*/
Vector getPosition();
/**
* Return object shape.
*
* @return Polygon points
*/
std::vector<Vector>& getShape();
/**
* Set object shape.
*
* @param shape Vector containing polygon poinst
*/
void setShape(std::vector<Vector> shape);
/**
* Return object facing.
*
* @return Object facing (true if facing right)
*/
bool getFacing();
/**
* Return object aim angle.
*
* @return Object aim angle
*/
float getAim();
/**
* Update object in physics simulation.
*/
virtual void tick (TimeMS tick_length);
/**
* Draw object
*
* @param gc CL_GraphicContext
*/
virtual void draw(CL_GraphicContext *gc);
};
// TODO: This could probably be moved somewhere else or removed
// completely.
struct Derivative {
Vector dx; // Velocity
Vector dv; // Acceleration
};
#endif