src/proto2/Physics.hh
author saiam
Fri, 28 Nov 2008 22:26:23 +0000
changeset 128 890ac82cdcc0
parent 123 7efb63402b2b
child 129 b1ae79a2d2f0
permissions -rw-r--r--
Documenting more, cleaning variables. This code needs some serious
rewriting. (And we havent too many features either)
#ifndef PHYSICS_HH
#define PHYSICS_HH

#include "Vector.hh"

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

typedef uint16_t TimeMS;

const TimeMS PHYSICS_TICK_MS = 10;

enum TerrainType {EMPTY, DIRT, ROCK};

const Vector DIRECTIONS[] = { Vector(0,-1), Vector(1,-1), Vector(1,0), Vector(1,1),
							Vector(0,1), Vector(-1,1), Vector(-1,0), Vector(-1,-1) };

// forward-declare
class PhysicsObject;
typedef Vector Force;
struct Derivative;

class PhysicsWorld {
    friend class PhysicsObject;
    
private:
    CL_Timer tick_timer;

    uint32_t tick_counter;
    
protected:
    std::vector<PhysicsObject*> objects;
    Vector gravity;
    Vector dimensions;


    std::vector<std::vector<TerrainType> > terrain;

    CL_SlotContainer slots;
    
    PhysicsWorld (Vector gravity, Vector dimensions);


public:
    
    /**
     * Adds objects to the physicsworld.
     *
     * @param object Pointer to PhysicsObject to add.
     */
    void addObject (PhysicsObject *object);
    
    /**
     * Advance one time step in physics simulation.
     */
    void tick (void);
    /**
     * Get current tick in physics simulation.
     */
    uint32_t getTick (void);

  
    /**
     * Generate random terrain.
     */
    void generateTerrain (int seed);

    /**
     * TODO: We'll have to think about this.
     */
    bool collided (Vector prevPos, Vector newPos);

    /**
     * Return a normal for the wall that has been hit.
     *
     * @param hitPoint The point of the wall that has been hit.
     * @param prevPoint The point from where we were coming.
     */
    Vector getNormal(Vector hitPoint, Vector prevPoint);

    /**
     * Return terrain type in specific position.
     *
     * @param x x-coordinate
     * @param y y-coordinate
     */
    TerrainType getType(int x, int y) const;
    /**
     * Return terrain type in specific position.
     *
     * @param pos Position vector
     */
    TerrainType getType(Vector pos) const;

    /**
     * Remove ground from the terrain. Removes a circle with given
     * radius.
     *
     * @param x center x coordinate
     * @param y center y coordinate
     * @param r circle radius
     */
    void removeGround(int x, int y, float r);
    
    /**
     * Remove ground from the terrain. Removes a circle with given
     * radius.
     *
     * @param pos circle center
     * @param r circle radius
     */
    void removeGround(Vector pos, float r);
};

class PhysicsObject {
protected:
    PhysicsWorld &world;
    
    float mass;
    Vector position;
    Vector velocity;
    float aim; // Aim direction (half circle)
    bool facingRight; // Player facing
    bool inAir; // Is the object "on the ground"

    // Shape of the object. We use a polygon with 4 edges
    // to make easy to draw with Clanlib. The coordinates
    // are relative to the center point.
    std::vector<Vector> shape;
    
    // Force queue that is emptied on every tick
    std::queue<Force> forceq;
    Vector posAfterTick;
    Vector velAfterTick;

    /**
     * @param shape Corners of the four sided polygon.
     */
    PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity);
    ~PhysicsObject() {}   

    /**
     * Adds force to the force queue. Force queue is emptied on each
     * tick. Forces that last over one tick are also handled. This
     * function is only used to handle in air movement.
     *
     * @param force Force vector.  
     * @param dt The time the force is applied.
     */
    virtual void applyForce (Force force);

    /**
     * Changes player aim
     */
    void changeAim(float da);

    /**
     * Set player facing.
     */ 
    void setFacing(bool right);

    /**
     * Called on network clients to sync state from server
     */
    void updatePhysics (Vector position, Vector velocity, bool inAir);

    /**
     * Handle ground movement
     *
     * @return new position
     */
    Vector walk (bool right);

    /**
     * Handle ground-jumping
     */
    void jump (void);

    /**
     * Handle ground-bounce
     */
    void bounce (Vector normal);

private:
    void updatePosition (void);
	bool possibleLocation (Vector loc);

    /**
     * Use RK4 to integrate the effects of force over a time intervall.
     */
    void integrate(Force force, TimeMS dt);
    Derivative evaluate(Force force, TimeMS dt, Derivative &d);
    Vector acceleration(const Force &force);

    virtual void onCollision() {}

public:
    Vector getPosition (void);
    std::vector<Vector>& getShape(void);
    void setShape (std::vector<Vector> shape);

    bool getFacing(void);
    float getAim(void);

    void tick (void);
};

struct Derivative {
    Vector dx; // Velocity
    Vector dv; // Acceleration
};



#endif