reorganize PhysicsObject/Player/Projectile lists so that PhysicsObject doesn't need to know about its subclasses anymore, and PhysicsWorld doesn't need to know about GameState
authorekku
Sat, 06 Dec 2008 17:51:19 +0000
changeset 222 293ddf4c067d
parent 221 fbc5db6fce45
child 223 2fcaf54ed37b
reorganize PhysicsObject/Player/Projectile lists so that PhysicsObject doesn't need to know about its subclasses anymore, and PhysicsWorld doesn't need to know about GameState
src/GameState.cc
src/GameState.hh
src/Graphics.cc
src/PhysicsObject.cc
src/PhysicsObject.hh
src/PhysicsWorld.cc
src/PhysicsWorld.hh
src/Player.cc
src/Player.hh
src/Projectile.cc
src/Projectile.hh
src/Terrain.hh
src/Weapon.hh
--- a/src/GameState.cc	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/GameState.cc	Sat Dec 06 17:51:19 2008 +0000
@@ -5,6 +5,10 @@
 
 GameState::GameState (void) : local_player(NULL), world(Vector(0, MAP_GRAVITY), Vector(MAP_WIDTH, MAP_HEIGHT)) { }
 
+void GameState::addProjectile (Projectile *projectile) {
+    projectiles.push_back(projectile);
+}
+
 LocalPlayer *GameState::getLocalPlayer (void) {
     return local_player;
 }
@@ -25,7 +29,18 @@
 void GameState::removePlayer (Player *player) { 
     player_list.remove(player);
 }
-
+    
+void GameState::draw(CL_GraphicContext *gc) {
+    // Draw world/terrain
+    world.draw(gc);
 
-
-
+    // Draw players
+    for (std::list<Player*>::iterator it = player_list.begin(); it != player_list.end(); it++) {
+        (*it)->draw(gc);
+    }
+    // Draw projectiles
+    for (std::list<Projectile*>::iterator it = projectiles.begin(); it != projectiles.end(); it++) {
+        (*it)->draw(gc);
+    }
+}
+ 
--- a/src/GameState.hh	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/GameState.hh	Sat Dec 06 17:51:19 2008 +0000
@@ -16,12 +16,15 @@
 class GameState {
 public:
     std::list<Player*> player_list;
+    std::list<Projectile*> projectiles;
     PhysicsWorld world;
 
     // only one local player is supported
     LocalPlayer *local_player;
 
     GameState (void);
+    
+    void addProjectile(Projectile *projectile);
 
     /*
      * This will return NULL if we don't have a local player - yet
@@ -29,10 +32,12 @@
     LocalPlayer *getLocalPlayer (void);
 
     void newLocalPlayer (LocalPlayer *player);        
-
     void newPlayer (Player *player);
 
     void removePlayer (Player *player);
+
+    virtual void draw(CL_GraphicContext *gc);
+
 };
 
 #endif
--- a/src/Graphics.cc	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/Graphics.cc	Sat Dec 06 17:51:19 2008 +0000
@@ -54,7 +54,7 @@
     gc->clear(CL_Color::white);
 
     // Draw terrain
-    state.world.draw(gc);
+    state.draw(gc);
 
     // Flip window buffer, sync
     win.flip(1);
--- a/src/PhysicsObject.cc	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/PhysicsObject.cc	Sat Dec 06 17:51:19 2008 +0000
@@ -1,15 +1,21 @@
-#include "Player.hh"
+
 #include "PhysicsObject.hh"
 #include "Engine.hh"
 
 #include <cmath>
 
-PhysicsObject::PhysicsObject (PhysicsWorld &world, float mass, 
-                              Vector position, Vector velocity)
-    : world(world), position(position), velocity(velocity),
-      mass(mass), inAir(true), aim(0), facingRight(true) {
-    // TODO: Is thir the right way to do this?
-    //world.addPlayerObject(this);
+PhysicsObject::PhysicsObject (PhysicsWorld &world, float mass, Vector position, Vector velocity) :
+    world(world), position(position), velocity(velocity), mass(mass), inAir(true), aim(0), facingRight(true), alive(true)
+{
+    world.addPhysicsObject(this);
+}
+
+PhysicsObject::~PhysicsObject (void) {
+    Engine::log(DEBUG, "PhysicsObject.destructor") << this /* << ": objects.size=" << ((int) world.objects.size()) */;
+
+    // world.objects.remove(this);
+
+    Engine::log(DEBUG, "PhysicsObject.destructor") << this /* << ": objects.size=" << ((int) world.objects.size()) */;
 }
 
 /**
@@ -103,10 +109,6 @@
     return true;
 }
 
-void func1() {
-
-}
-
 /**
  * Updates object speed and position. This function organises force
  * integration and collision detection.
@@ -153,10 +155,9 @@
         }
     }
 
-    if(!possibleLocation(position)) {
-        Engine::log(DEBUG, "great failure") << "great failure";
-        func1();
-    }
+    if (!possibleLocation(position))
+        Engine::log(DEBUG, "PhysicsObject.updatePosition") << "impossible location: " << position;
+
     Vector newPosition;
     Vector velAfterTick;
     // Calculate new position and velocity to the given references
@@ -196,26 +197,28 @@
     }
    
     
-    if(!possibleLocation(reached)) {
-        Engine::log(DEBUG, "PhysicsObject.updatePosition") << "inside ground. diffVec: " << diffVec;
-        func1();
-    }
+    if (!possibleLocation(reached))
+        Engine::log(DEBUG, "PhysicsObject.updatePosition") << "impossible location: " << position << ", diffVec=" << diffVec;
 
     // In case of some float error check the final coordinate
-    if(!collided) {
-        if(!possibleLocation(newPosition)) {
+    if (!collided) {
+        if (!possibleLocation(newPosition)) {
             newPosition = reached;
         } else {
             // This means everything was ok, so no need to do anything
         }
+
+        this->position = newPosition;
+
     } else {
         newPosition = reached;
         this->position = newPosition;
+
+        // the following may delete this object, so it must be the last thing called
         onCollision();
-        //TODO: It should be moved before onCollision, for Shots
+
+        return;
     }
-    this->position = newPosition;
-//    Engine::log(DEBUG, "PhysicsObject.updatePosition") << "Pos: " << this->position;
 }
 
 /**
@@ -304,6 +307,10 @@
     return this->position;
 }
 
+Vector PhysicsObject::getVelocity () {
+    return this->velocity;
+}
+
 bool PhysicsObject::getFacing() {
     return this->facingRight;
 }
@@ -323,6 +330,23 @@
 void PhysicsObject::tick (TimeMS tick_length) {
     this->updatePosition(tick_length);
 }
+    
+void PhysicsObject::destroy (void) {
+    alive = false;
+}
+    
+bool PhysicsObject::isDestroyed (void) {
+    return !alive;
+}
+    
+bool PhysicsObject::removeIfDestroyed (void) {
+    if (!alive) {
+        delete this;
+        return true;
+    } else {
+        return false;
+    }
+}
 
 void PhysicsObject::draw(CL_GraphicContext *gc) {
     CL_Quad player(
--- a/src/PhysicsObject.hh	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/PhysicsObject.hh	Sat Dec 06 17:51:19 2008 +0000
@@ -21,9 +21,6 @@
  */
 class PhysicsObject {
 protected:
-    // This probably shouldn't be done this way.
-
-
     Vector position;
     Vector velocity;
     float mass;
@@ -34,9 +31,11 @@
     float aim; // Aim direction (half circle)
     bool facingRight; // Player facing
 
+    bool alive;
+
     PhysicsObject(PhysicsWorld &world, float mass, Vector position, 
                   Vector velocity);
-    ~PhysicsObject() {}
+    virtual ~PhysicsObject (void);
 
 
     /**
@@ -159,6 +158,13 @@
     Vector getPosition();
 
     /**
+     * Get current object velocity.
+     *
+     * @return Velocity vector
+     */
+    Vector getVelocity();
+
+    /**
      * Return object shape.
      *
      * @return Polygon points
@@ -187,6 +193,21 @@
     float getAim();
 
     /**
+     *  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);
+
+    /**
      * Update object in physics simulation.
      */
     virtual void tick (TimeMS tick_length);
--- a/src/PhysicsWorld.cc	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/PhysicsWorld.cc	Sat Dec 06 17:51:19 2008 +0000
@@ -1,64 +1,28 @@
 
-#include "GameState.hh"
 #include "PhysicsWorld.hh"
 #include "Engine.hh"
 
-PhysicsWorld::PhysicsWorld (Vector gravity, Vector dimensions)
-    : Terrain(1337), tick_timer(PHYSICS_TICK_MS), dimensions(dimensions),
-      gravity(gravity) {
+#include <functional>
+
+PhysicsWorld::PhysicsWorld (Vector gravity, Vector dimensions) :
+     Terrain(1337), tick_timer(PHYSICS_TICK_MS), dimensions(dimensions), gravity(gravity)
+{
     slots.connect(tick_timer.sig_tick(), this, &PhysicsWorld::tick);
     tick_timer.start();
 }
 
-void PhysicsWorld::addPlayerObject (PhysicsObject *object) {
-    players.push_back(object);
-}
-
-void PhysicsWorld::addProjectile (Projectile *projectile) {
-    projectiles.push_back(projectile);
+void PhysicsWorld::addPhysicsObject (PhysicsObject *po) {
+    objects.push_back(po);
 }
 
-/**
- * Function pointer used to clear the projectile list
- * from those that have already been destroyd.
- */
-bool isDestroyedProjectile (Projectile* po) { 
-    //    return po->isDestroyed();
-    if (po->isDestroyed() || (po->world.tick_timer.get_ticks() > (po->birth_tick + po->age))) {
-        Engine::log(DEBUG, "PhysicsWorld.isDestroyedProjectile") << "Destroying projectile: " << po;
-        delete po;
-        return true;
-    } else {
-        return false;
-    }
-}
 
 void PhysicsWorld::tick (TimeMS tick_length) {
-    //    Engine::log(DEBUG, "physics.apply_force") << "*tick*";
-
-    for (std::list<PhysicsObject*>::iterator i = players.begin(); i != players.end(); i++) {
+    for (std::list<PhysicsObject*>::iterator i = objects.begin(); i != objects.end(); i++) {
+//        Engine::log(DEBUG, "PhysicsWorld.tick") << (*i);
         (*i)->tick(tick_length); 
     }
 
-    for (std::list<Projectile*>::iterator i = projectiles.begin(); i != projectiles.end(); i++) {
-        (*i)->tick(tick_length);
-    }
-
-    // Delete destroyed projectiles
-    std::list<Projectile*>::iterator new_end = remove_if(projectiles.begin(), projectiles.end(), isDestroyedProjectile);
-    projectiles.erase(new_end, projectiles.end());
+    // Delete destroyed objects
+    objects.remove_if(std::mem_fun(&PhysicsObject::removeIfDestroyed));
 }
 
-void PhysicsWorld::draw(CL_GraphicContext *gc) {
-    Terrain::draw(gc);
-   
-    // Draw players
-    for (std::list<PhysicsObject*>::iterator it = players.begin(); it != players.end(); it++) {
-        (*it)->draw(gc);
-    }
-    // Draw projectiles
-    for (std::list<Projectile*>::iterator it = projectiles.begin(); it != projectiles.end(); it++) {
-        (*it)->draw(gc);
-    }
-}
- 
--- a/src/PhysicsWorld.hh	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/PhysicsWorld.hh	Sat Dec 06 17:51:19 2008 +0000
@@ -13,7 +13,6 @@
 class PhysicsWorld;
 
 #include "PhysicsObject.hh"
-#include "Projectile.hh"
 #include "Vector.hh"
 #include "Timer.hh"
 #include "Config.hh"
@@ -29,9 +28,7 @@
 
     
 protected:
-    std::list<PhysicsObject*> players;
-    std::list<Projectile*> projectiles;
-//    std::vector<PhysicsObject*> objects;
+    std::list<PhysicsObject*> objects;
 
     // Contains connections between signals and slots
     CL_SlotContainer slots;
@@ -40,29 +37,19 @@
     Vector dimensions;
     Vector gravity;
 
-
-
 public:
-
     // Someone is going to kill me for this
     Timer tick_timer;
 
-
     PhysicsWorld(Vector gravity, Vector dimensions);
 
-    // 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 addPlayerObject(PhysicsObject *object);
+    void addPhysicsObject(PhysicsObject *object);
     
-    void addProjectile(Projectile *projectile);
-
     /**
      * Advance one time step in physics simulation.
      */
@@ -75,8 +62,6 @@
      */
     uint32_t getTick();
 
-    virtual void draw(CL_GraphicContext *gc);
-
     // TODO This should probably be protected or in GameStat or in GameStatee
 };
 
--- a/src/Player.cc	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/Player.cc	Sat Dec 06 17:51:19 2008 +0000
@@ -18,7 +18,9 @@
 const int img_width = 10;
 
 Player::Player(GameState &state, Vector position, bool visible) : 
-    PhysicsObject(state.world, PLAYER_MASS, position, Vector(0, 0)), state(state), visible(visible), arsenal(), selectedWeapon(0), changing(false), animation_step(0) {
+    PhysicsObject(state.world, PLAYER_MASS, position, Vector(0, 0)), state(state), visible(visible), arsenal(),
+    selectedWeapon(0), changing(false), animation_step(0) //, rope(*this) 
+{
     // TODO: arsenal's size should be affected by some value
     // and weapons should be loaded from somewhere, not generated here
     for (int i = 0; i < 5; i++) {
@@ -38,9 +40,6 @@
 
     // XXX: this should be a PhysicsObject constructor arg
     collision_elasticity = PLAYER_COLLISION_ELASTICITY;
-
-    // add to player-object list
-    world.addPlayerObject(this);
 }
  
 void Player::handleDig (Vector position, float radius) {
--- a/src/Player.hh	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/Player.hh	Sat Dec 06 17:51:19 2008 +0000
@@ -9,16 +9,20 @@
 #include "PhysicsObject.hh"
 #include "Input.hh"
 #include "Weapon.hh"
+//#include "Rope.hh"
 #include <vector>
 
 class Player : public PhysicsObject {
+    public:
+        GameState &state;
+
     protected:
-        GameState &state;
         bool visible;
         std::vector<Weapon> arsenal;
         unsigned int selectedWeapon; //unsigned for x%sW not to fail
         bool changing;
 
+//        Rope rope;
         int animation_step;
 
         // default constructor for use with virtual inheritance... it's not defined
--- a/src/Projectile.cc	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/Projectile.cc	Sat Dec 06 17:51:19 2008 +0000
@@ -2,7 +2,7 @@
 #include "Timer.hh"
 
 Projectile::Projectile(GameState &state, Vector position, Vector velocity, bool visible, float radius, TickCount age) :
-    PhysicsObject(state.world, PLAYER_MASS, position, velocity), state(state), visible(visible), radius(radius), destroyed(false), age(age) {
+    PhysicsObject(state.world, PLAYER_MASS, position, velocity), state(state), visible(visible), radius(radius), age(age) {
     birth_tick = world.tick_timer.get_ticks();
     // Don't think these are needed anymore
     std::vector<Vector> shape(4);
@@ -14,17 +14,17 @@
 
     target_visible = false;
     collision_elasticity = 0.9; // = shotType.elasticity
-    world.addProjectile(this);
+    state.addProjectile(this);
 }
-
+    
+Projectile::~Projectile (void) {
+    state.projectiles.remove(this);
+}
  
 void Projectile::onCollision() {
     world.removeGround(position, radius);
-    this->destroyed = true;
-}
-
-bool Projectile::isDestroyed (void) const {
-    return this->destroyed;
+    
+    destroy();
 }
 
 void Projectile::draw(CL_GraphicContext *gc) const {
@@ -57,3 +57,13 @@
         }
     }
 }
+    
+void Projectile::tick (TimeMS dt) {
+    // expire projectiles
+    if (world.tick_timer.get_ticks() > birth_tick + age)
+        destroy();
+
+    // super
+    PhysicsObject::tick(dt);
+}
+
--- a/src/Projectile.hh	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/Projectile.hh	Sat Dec 06 17:51:19 2008 +0000
@@ -3,8 +3,8 @@
  
 class Projectile;
 
+#include "GameState.hh"
 #include "PhysicsObject.hh"
-#include "GameState.hh"
 #include "Timer.hh"
 
 class Projectile : public PhysicsObject {
@@ -12,7 +12,6 @@
     GameState &state;
     bool visible;
     bool target_visible;
-    bool destroyed;
     float radius;
 public:
 
@@ -20,12 +19,13 @@
     TickCount age;
 
     Projectile(GameState &state, Vector position, Vector velocity, bool visible, float radius, TickCount age=1000000000);
-    ~Projectile() {};
+    virtual ~Projectile (void);
 
-    bool isDestroyed (void) const;
-    virtual void draw(CL_GraphicContext *gc) const;
-private:
-    virtual void onCollision();
+    virtual void draw (CL_GraphicContext *gc) const;
+
+protected:
+    virtual void onCollision (void);
+    virtual void tick (TimeMS dt);
 };
  
 #endif
--- a/src/Terrain.hh	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/Terrain.hh	Sat Dec 06 17:51:19 2008 +0000
@@ -142,6 +142,7 @@
      * @param gc CL_GraphicContext
      */
     virtual void draw(CL_GraphicContext *gc);
+
     /**
      * Draw part of the terrain for given graphiscontext.
      *
--- a/src/Weapon.hh	Sat Dec 06 16:17:05 2008 +0000
+++ b/src/Weapon.hh	Sat Dec 06 17:51:19 2008 +0000
@@ -5,6 +5,7 @@
 class Weapon;
 
 #include "GameState.hh"
+#include "Projectile.hh"
 #include "Timer.hh"
 #include <string>