compiles cleanly with -Wall -Wextra -Wconversion, not tested, but that shouldn't break anything :)
#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;
enum ObjectType { PLAYER, PROJECTILE, ROPE };
enum FacingDirection {
FACING_LEFT,
FACING_RIGHT
};
/**
* PhysicObject class. A basic PhysicsObject class.
*/
class PhysicsObject {
public:
PhysicsWorld &world;
protected:
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)
FacingDirection facing; // Player facing
bool alive;
bool shouldDelete;
ObjectType type;
PhysicsObject *pivot;
PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity, ObjectType type,
float collision_elasticity, bool enabled = true);
virtual ~PhysicsObject (void);
/**
* Add force to the force queue to be applied on next tick.
*
* @param force Force vector
*/
void applyForce(Force force, TimeMS dt = PHYSICS_TICK_MS);
/**
* 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 (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 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, FacingDirection facing, float aim);
/**
* Put object to the objects list so that its movement will be calculated.
*/
void enable (void);
/**
* Remove object from the objects list but don't delete the object itself.
*/
void disable (void);
private:
// Shape of the object. Edge points of the shape polygon.
std::vector<Vector> shape;
// Force queue that is emptied on every tick
std::queue<std::pair<Force, TimeMS> > 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);
/**
* Handle ground movement.
*
* @param right Boolean describing the movement direction.
* @return New position
*/
void walk(TimeMS, bool right);
Vector walk_one_step(float, bool);
/**
* Define object behaviour on collisions.
*
* XXX: make this pure-virtual
*/
virtual void onCollision (Vector collisionPoint, PhysicsObject *other);
public:
/**
* Checks if it is possible for the object to be in the given
* location.
*/
bool possibleLocation(Vector loc);
/**
* Get current object position.
*
* @return Position vector
*/
Vector getPosition (void) const;
/**
* Get current object screen coordinates
*
* @return PixelCoordinate position
*/
PixelCoordinate getCoordinate (void) const;
/**
* Get current object velocity.
*
* @return Velocity vector
*/
Vector getVelocity() const;
/**
* Return object shape.
*
* @return Polygon points
*/
const std::vector<Vector>& getShape() const;
/**
* 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)
*/
FacingDirection getFacing() const;
/**
* Return object aim angle.
*
* @return Object aim angle
*/
float getAim() const;
/**
* Returns facing+aim as a unit vector
*/
Vector getDirection (void) const;
/**
* Mark object as destroyed, it will be delete'd later
*/
void destroy (void);
/*
* Had the object been destroyed?
*/
bool isDestroyed (void);
/**
* Delete ourselves if we've been destroyed and return true, else return false
*/
bool removeIfDestroyed (void);
/**
* Sets this object's pivot to the given value, which will then exert a force on this object
*/
void setPivot (PhysicsObject *pivot);
/**
* Checks if object collides with other objects
*
* @param obj Other PhysicsObject
*/
bool collides (const PhysicsObject &obj);
/**
* Compute the force that this object (as a pivot) exerts on the given object
*/
virtual float getPivotForce (PhysicsObject *bob);
/**
* Update object in physics simulation.
*/
virtual void tick (TimeMS tick_length);
};
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