#ifndef PHYSICS_OBJECT_HH
#define PHYSICS_OBJECT_HH
#include <ClanLib/display.h>
#include <utility>
// Forward declares
class PhysicsObject;
struct Derivative;
#include "PhysicsWorld.hh"
#include "Vector.hh"
#include "Timer.hh"
#include "Config.hh"
// Type definitions
typedef Vector Force;
/** Specifies possible object types. */
enum ObjectType { PLAYER, PROJECTILE, ROPE };
/** Specifies possible facing directions for objects. */
enum FacingDirection {
FACING_LEFT,
FACING_RIGHT
};
/**
* PhysicsObject class. Represents an object in the physics simulation.
*/
class PhysicsObject {
public:
/** Reference to PhysicsWorld. */
PhysicsWorld &world;
protected:
/** Object position. */
Vector position;
/** Object position on previous physics tick. */
Vector previousPosition;
/** Object velocity */
Vector velocity;
/** Object mass. */
float mass;
/** Tells if the object is "on the ground" */
bool inAir;
/** Object elasticity. */
float collision_elasticity;
// Attributes for players
/** Aim angle in radians. */
float aim;
/** Player facing. */
FacingDirection facing;
/** Specifies if the player is alive (or dead). */
bool alive;
/** True if player object should be removed from the game. */
bool shouldDelete;
/** Type of the object */
ObjectType type;
/** Pivot object for this object. */
PhysicsObject *pivot;
/**
* Class constructor
*
* @param world Reference to PhysicsWorld
* @param mass Object mass
* @param position Object position
* @param velocity Object velocity
* @param type Object type
* @param collision_elasticity Object elasticity
* @param enabled Is the object currently part of the simulation
*/
PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity, ObjectType type,
float collision_elasticity, bool enabled = true);
virtual ~PhysicsObject (void);
/**
* Apply a force to the object. The force is applied to the object
* on the next physics tick.
*
* @param force Force vector
*/
void applyForce(Force force, TimeMS dt = PHYSICS_TICK_MS);
/**
* Change player aim. This function takes care that aim angle
* stays inside limits.
*
* @param da Aim angle change in radians
*/
void changeAim(float da);
/**
* Set player facing.
*
* @param facingRight True if player is facing right.
*/
void setFacing (FacingDirection facing);
/**
* Makes the player jump in the air.
*
* @param direction -1: jump left, 0: jump up, 1: jump right
*/
void jump (int direction);
/**
* Handle object 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, FacingDirection facing, float aim);
/**
* Put the object in the physics simulation. When the object is in
* the physics simulation it's movements will be calculated.
*/
void enable (void);
/**
* Remove object from the objects physics simulation. When the
* object isn't in the physics simulation it won't be deleted but
* its movements will not be calculated.
*/
void disable (void);
private:
/** Objects shape. Edgepoints of the polygon */
std::vector<Vector> shape;
/** Object force queue. The queue is emptied on every physics
tick.*/
std::queue<std::pair<Force, TimeMS> > forceq;
/**
* Handle player movement and apply forces.
*
* @param dt Time intervall
*/
void updatePosition (TimeMS dt);
/**
* Use RK4 to integrate the effects of force over a time interwall.
*
* @param force Force to integrate
* @param dt Time intervall
* @param posAfterTick Reference to object postition after integration.
* @param velAfterTick Reference to object velocity after integration.
*/
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
* @return 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);
/**
* Handle ground movement.
*
* @param right Boolean describing the movement direction.
* @return New position
*/
void walk (TimeMS, bool right);
Vector walk_one_step (float, bool);
public:
/**
* Define object behaviour on collisions.
*
* @param collisionPoint Point of collision.
* @param other The other object we have collided with.
*/
virtual void onCollision (Vector collisionPoint, PhysicsObject *other = NULL);
/**
* Get object type.
*
* @return Object type
*/
ObjectType getType (void) const;
/**
* Checks if it is possible for the object to be in the given
* location.
*
* @param loc Location
*/
bool possibleLocation (Vector loc);
/**
* Get current object position.
*
* @return Position vector
*/
Vector getPosition (void) const;
/**
* Set previous object position.
*
* @param Position vector
*/
void setPosition (Vector pos);
/**
* Get previous object position.
*
* @return Position vector
*/
Vector getPreviousPosition (void) const;
/**
* Get current object screen coordinates
*
* @return PixelCoordinate position
*/
PixelCoordinate getCoordinate (void) const;
/**
* Get current object velocity.
*
* @return Velocity vector
*/
Vector getVelocity (void) const;
/**
* Return object shape.
*
* @return Polygon points
*/
const std::vector<Vector>& getShape (void) const;
/**
* Set object shape.
*
* @param shape Vector containing polygon points
*/
void setShape(std::vector<Vector> shape);
/**
* Return object facing.
*
* @return Object facing (true if facing right)
*/
FacingDirection getFacing() const;
/**
* Return object aim angle.
*
* @return Object aim angle
*/
float getAim() const;
/**
* Get object direction.
*
* @return Unit vector to facing+aim
*/
Vector getDirection (void) const;
/**
* Mark object as destroyed, it will be delete'd later
*/
void destroy (void);
/**
* Check if the object is alive.
*
* @return Is the object alive?
*/
bool isAlive (void);
/**
* Tells the state of the object.
*
* @return True if object has been destroyed.
*/
bool removeIfDestroyed (void);
/**
* Set object pivot.
*
* @param pivot Pivot object
*/
void setPivot (PhysicsObject *pivot);
/**
* Return the pivot object pointer.
*/
PhysicsObject *getPivot (void);
/**
* Checks if object collides with other objects
*
* @param obj Other PhysicsObject
* @return Did we collide?
*/
bool collides (const PhysicsObject &obj);
/**
* Compute the force that this object (as a pivot) exerts on the given object
*
* @param bob Othe object
* @return Force
*/
virtual Vector getPivotForce (void);
/**
* Update object in physics simulation.
*
* @param tick_length Length of the physics tick
*/
virtual void tick (TimeMS tick_length);
};
/** Helper struct for the integration */
struct Derivative {
Vector dx; // Velocity
Vector dv; // Acceleration
};
/**
* Returns the "sign" of the cross product between given points. In
* practice the sign of the return value tels on which side of the
* line drawn between p1 and p2 the point p3 is.
*
* @param p1 Line start point
* @param p2 Line end point
* @param p3 Point
* @return Variable, the sign of which tells on which side of the line p3 is.
*/
int8_t crossProduct(const Vector &p1, const Vector &p2, const Vector &p3);
#endif