src/PhysicsObject.hh
author terom
Mon, 15 Dec 2008 14:34:14 +0000
changeset 372 a03d7d716dd9
parent 322 f94a5c192097
child 423 947ab54de4b7
permissions -rw-r--r--
remove redundant doc/doxygen directory
#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