src/proto2/Physics.hh
author nireco
Tue, 02 Dec 2008 00:23:16 +0000
changeset 174 073f25a84f60
parent 170 fe74105c07ea
child 180 bfe1077edab3
permissions -rw-r--r--
removed bad comment
#ifndef PHYSICS_HH
#define PHYSICS_HH

#include <vector>
#include <queue>
#include <ClanLib/core.h>
#include <ClanLib/display.h>

#include "Vector.hh"
#include "Config.hh"
#include "Terrain.hh"

// Forward declares
class PhysicsWorld;
class PhysicsObject;
class PlayerObject;
class ProjectileObject;
class Shape;
struct Derivative;

// Type definitions
typedef uint16_t TimeMS;
typedef Vector Force;

/**
 * PhysicsWorld class. PhysicsWorld contains PhysicsObjects that are
 * simulated in the PhysicsWorld.
 */
class PhysicsWorld : public Terrain {
    friend class PhysicsObject;

private:
    CL_Timer tick_timer;
    uint32_t tick_counter;

    //    Terrain terrain;

protected:
    //std::vector<PlayerObject*> players;
    //std::vector<ProjectileObject*> projectiles;
    std::vector<PhysicsObject*> objects;

    // Contains connections between signals and slots
    CL_SlotContainer slots;

    PhysicsWorld(Vector gravity, Vector dimensions);

    // TODO: Should these be somewhere else?
    Vector dimensions;
    Vector gravity;



public:
    // TODO: Replace addObject with these?
    //void addPlayerObject(PlayerObject *object);
    //void addProjectileObject(ProjectileObject *object);
    
    /**
     * Add object to the PhysicsWorld.
     *
     * @param object Pointer to the PhysicsObject to add.
     */
    void addObject(PhysicsObject *object);

    /**
     * Advance one time step in physics simulation.
     */
    void tick();

    /**
     * Get current tick in physics simulation.
     *
     * @return tick Current simulation tick.
     */
    uint32_t getTick();

};

/**
 * PhysicObject class. A basic PhysicsObject class.
 */
class PhysicsObject {
protected:
    // This probably shouldn't be done this way.
    PhysicsWorld &world;

    Vector position;
    Vector velocity;
    float mass;
    bool inAir; // Is the object "on the ground"

    // 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
     */
    void updatePhysics(Vector position, Vector velocity, bool inAir);

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();

    // 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
     */
    Vector walk(bool right);

    /*
     * 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:
    /**
     * 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.
     */
    void tick();

    /**
     * Draw object
     *
     * @param gc CL_GraphicContext
     */
    void draw(CL_GraphicContext *gc);
};

// TODO: This could probably be moved somewhere else or removed
// completely.
struct Derivative {
    Vector dx; // Velocity
    Vector dv; // Acceleration
};


// TODO: These are drafts
/**
 * PlayerObject class. Represents a player in the physics engine.
 */
//class PlayerObject : public PhysicsObject {

//};

/**
 * ProjectileObject class. Represents different projectiles in the
 * physics (i.e. not players) in the physics engine.
 */
//class ProjectileObject : public PhysicsObject {

//};

#endif