- changed way badguy removal is handled (ie. with a flag now)
authorIngo Ruhnke <grumbel@gmx.de>
Thu, 22 Apr 2004 19:15:22 +0000 (19:15 +0000)
committerIngo Ruhnke <grumbel@gmx.de>
Thu, 22 Apr 2004 19:15:22 +0000 (19:15 +0000)
- changed some pointers to const references in collision code

SVN-Revision: 648

src/badguy.cpp
src/badguy.h
src/collision.cpp
src/collision.h
src/leveleditor.cpp
src/player.cpp
src/special.cpp
src/world.cpp
src/world.h

index c09678b..5331046 100644 (file)
@@ -145,8 +145,8 @@ std::string badguykind_to_string(BadGuyKind kind)
     }
 }
 
-void
-BadGuy::init(float x, float y, BadGuyKind kind_, bool stay_on_platform_)
+BadGuy::BadGuy(float x, float y, BadGuyKind kind_, bool stay_on_platform_)
+  : removable(false)
 {
   base.x   = x;
   base.y   = y;    
@@ -207,9 +207,9 @@ BadGuy::init(float x, float y, BadGuyKind kind_, bool stay_on_platform_)
   }
 
   // if we're in a solid tile at start correct that now
-  if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(&base)) {
+  if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(base)) {
     printf("Warning: badguy started in wall!.\n");
-    while(collision_object_map(&base))
+    while(collision_object_map(base))
       --base.y;
   }
 }
@@ -276,7 +276,7 @@ BadGuy::action_laptop(float frame_ratio)
           base.x = tux.base.x - 16;
           base.y = tux.base.y + tux.base.height/1.5 - base.height;
         }
-      if(collision_object_map(&base))
+      if(collision_object_map(base))
         {
           base.x = tux.base.x;
           base.y = tux.base.y + tux.base.height/1.5 - base.height;
@@ -408,7 +408,7 @@ BadGuy::fall()
 void
 BadGuy::remove_me()
 {
-  World::current()->remove_bad_guy(this);
+  removable = true;
 }
 
 void
@@ -856,7 +856,7 @@ BadGuy::squish(Player* player)
     World::current()->add_score(base.x - scroll_x, base.y, 50 * player_status.score_multiplier);
     play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
     player_status.score_multiplier++;
-    remove_me();     
+    remove_me();
     return;
 
   } else if(kind == BAD_BSOD) {
@@ -960,6 +960,7 @@ BadGuy::collision(void *p_c_object, int c_object, CollisionType type)
     bump();
     return;
   }
+
   if(type == COLLISION_SQUISH) {
     Player* player = static_cast<Player*>(p_c_object);
     squish(player);
index 29d5a19..c7b03cc 100644 (file)
@@ -112,6 +112,7 @@ public:
   Direction dir;
 
 private:
+  bool removable;
   bool seen;
   base_type old_base;
   Timer timer;
@@ -123,7 +124,7 @@ private:
   int animation_offset;
 
 public:
-  void init(float x, float y, BadGuyKind kind, bool stay_on_platform);
+  BadGuy(float x, float y, BadGuyKind kind, bool stay_on_platform);
 
   void action(float frame_ratio);
   void draw();
@@ -135,7 +136,14 @@ public:
    * screen. Some badguys like the flame might ignore this.
    */
   void kill_me();
-  
+
+  /** remove ourself from the list of badguys. WARNING! This function will
+   * invalidate all members. So don't do anything else with member after calling
+   * this.
+   */
+  void remove_me();  
+  bool is_removable() const { return removable; }
 private:
   void action_bsod(float frame_ratio);
   void action_laptop(float frame_ratio);
@@ -153,13 +161,10 @@ private:
   /** handles falling down. disables gravity calculation when we're back on
    * ground */
   void fall();
-  /** remove ourself from the list of badguys. WARNING! This function will
-   * invalidate all members. So don't do anything else with member after calling
-   * this.
-   */
-  void remove_me();  
+
   /** let the player jump a bit (used when you hit a badguy) */
   void make_player_jump(Player* player);
+
   /** check if we're running left or right in a wall and eventually change
    * direction
    */
index 15a8b8b..1c96d91 100644 (file)
 #include "level.h"
 #include "tile.h"
 
-bool rectcollision(base_type* one, base_type* two)
+bool rectcollision(const base_type& one, const base_type& two)
 {
-  return (one->x >= two->x - one->width + 1  &&
-          one->x <= two->x + two->width - 1  &&
-          one->y >= two->y - one->height + 1 &&
-          one->y <= two->y + two->height - 1);
+  return (one.x >= two.x - one.width + 1  &&
+          one.x <= two.x + two.width - 1  &&
+          one.y >= two.y - one.height + 1 &&
+          one.y <= two.y + two.height - 1);
 }
 
-bool rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y)
+bool rectcollision_offset(const base_type& one, const base_type& two, float off_x, float off_y)
 {
-  return (one->x >= two->x - one->width +off_x + 1 &&
-          one->x <= two->x + two->width + off_x - 1 &&
-          one->y >= two->y - one->height + off_y + 1 &&
-          one->y <= two->y + two->height + off_y - 1);
+  return (one.x >= two.x - one.width  + off_x + 1 &&
+          one.x <= two.x + two.width  + off_x - 1 &&
+          one.y >= two.y - one.height + off_y + 1 &&
+          one.y <= two.y + two.height + off_y - 1);
 }
 
-bool collision_object_map(base_type* pbase)
+bool collision_object_map(const base_type& pbase)
 {
-  int v = (int)pbase->height / 16;
-  int h = (int)pbase->width / 16;
+  int v = (int)pbase.height / 16;
+  int h = (int)pbase.width / 16;
 
-  if(issolid(pbase->x + 1, pbase->y + 1) ||
-     issolid(pbase->x + pbase->width -1, pbase->y + 1) ||
-     issolid(pbase->x +1, pbase->y + pbase->height -1) ||
-     issolid(pbase->x + pbase->width -1, pbase->y + pbase->height - 1))
+  if(issolid(pbase.x + 1, pbase.y + 1) ||
+     issolid(pbase.x + pbase.width -1, pbase.y + 1) ||
+     issolid(pbase.x +1, pbase.y + pbase.height -1) ||
+     issolid(pbase.x + pbase.width -1, pbase.y + pbase.height - 1))
     return true;
 
   for(int i = 1; i < h; ++i)
     {
-      if(issolid(pbase->x + i*16,pbase->y + 1))
+      if(issolid(pbase.x + i*16,pbase.y + 1))
         return true;
     }
 
   for(int i = 1; i < h; ++i)
     {
-      if(  issolid(pbase->x + i*16,pbase->y + pbase->height - 1))
+      if(  issolid(pbase.x + i*16,pbase.y + pbase.height - 1))
         return true;
     }
 
   for(int i = 1; i < v; ++i)
     {
-      if(  issolid(pbase->x + 1, pbase->y + i*16))
+      if(  issolid(pbase.x + 1, pbase.y + i*16))
         return true;
     }
   for(int i = 1; i < v; ++i)
     {
-      if(  issolid(pbase->x + pbase->width - 1, pbase->y + i*16))
+      if(  issolid(pbase.x + pbase.width - 1, pbase.y + i*16))
         return true;
     }
 
@@ -155,18 +155,18 @@ void collision_swept_object_map(base_type* old, base_type* current)
           steps--;
         }
 
-      if(collision_object_map(old))
+      if(collision_object_map(*old))
         {
           switch(h)
             {
             case 1:
               current->y = old->y - yd;
-              while(collision_object_map(current))
+              while(collision_object_map(*current))
                 current->y -= yd;
               break;
             case 2:
               current->x = old->x - xd;
-              while(collision_object_map(current))
+              while(collision_object_map(*current))
                 current->x -= xd;
               break;
             case 3:
@@ -174,7 +174,7 @@ void collision_swept_object_map(base_type* old, base_type* current)
               yt = current->y;
               current->x = old->x - xd;
               current->y = old->y - yd;
-              while(collision_object_map(current))
+              while(collision_object_map(*current))
                 {
                   current->x -= xd;
                   current->y -= yd;
@@ -182,20 +182,20 @@ void collision_swept_object_map(base_type* old, base_type* current)
 
               temp = current->x;
               current->x = xt;
-              if(!collision_object_map(current))
+              if(!collision_object_map(*current))
                 break;
               current->x = temp;
               temp = current->y;
               current->y = yt;
 
-              if(!collision_object_map(current))
+              if(!collision_object_map(*current))
                 {
                   break;
                 }
               else
                 {
                   current->y = temp;
-                  while(!collision_object_map(current))
+                  while(!collision_object_map(*current))
                     current->y += yd;
                  current->y -= yd;
                   break;
index 3f6db25..4a009e5 100644 (file)
@@ -40,11 +40,11 @@ enum CollisionType {
     COLLISION_SQUISH
 };
 
-bool rectcollision(base_type* one, base_type* two);
-bool rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y);
+bool rectcollision(const base_type& one, const base_type& two);
+bool rectcollision_offset(const base_type& one, const base_type& two, float off_x, float off_y);
 
 void collision_swept_object_map(base_type* old, base_type* current);
-bool collision_object_map(base_type* object);
+bool collision_object_map(const base_type& object);
 
 /** Return a pointer to the tile at the given x/y coordinates */
 Tile* gettile(float x, float y);
index 6933e39..2984891 100644 (file)
@@ -92,10 +92,7 @@ struct LevelEditorWorld
 
   void add_bad_guy(float x, float y, BadGuyKind kind)
   {
-    bad_guys.push_back(BadGuy());
-    BadGuy& new_bad_guy = bad_guys.back();
-  
-    new_bad_guy.init(x,y,kind, false /* stay_on_platform */);
+    bad_guys.push_back(BadGuy(x,y,kind, false /* stay_on_platform */));
   }
 
   void activate_bad_guys()
index 0c1599b..7a387a2 100644 (file)
@@ -203,10 +203,11 @@ Player::action(double frame_ratio)
       // special exception for cases where we're stuck under tiles after
       // being ducked. In this case we drift out
       if(!duck && on_ground() && old_base.x == base.x && old_base.y == base.y
-         && collision_object_map(&base)) {
-        base.x += frame_ratio * WALK_SPEED * (dir ? 1 : -1);
-        previous_base = old_base = base;
-      }
+         && collision_object_map(base))
+        {
+          base.x += frame_ratio * WALK_SPEED * (dir ? 1 : -1);
+          previous_base = old_base = base;
+        }
       keep_in_bounds();
 
       // Land:
index 0bb4a1a..33878cf 100644 (file)
@@ -295,7 +295,7 @@ Upgrade::collision(void* p_c_object, int c_object)
           pplayer->size = BIG;
           pplayer->base.height = 64;
          pplayer->base.y -= 32;
-         if(collision_object_map(&pplayer->base))
+         if(collision_object_map(pplayer->base))
             {
               pplayer->base.height = 32;
               pplayer->base.y += 32;
index 27a06c2..655c60a 100644 (file)
@@ -20,6 +20,7 @@
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
 
+#include <iostream>
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
@@ -72,11 +73,9 @@ World::World(const std::string& subset, int level_nr)
 
 World::~World()
 {
-  for (unsigned int i = 0; i < bad_guys.size(); ++i)
-    {
-      delete bad_guys[i];
-    }
-
+  for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
+    delete *i;
+  
   halt_music(); // just to be sure (because levelmusic is freed now)
   delete level;
 }
@@ -172,8 +171,8 @@ World::draw()
   for (unsigned int i = 0; i < bouncy_bricks.size(); ++i)
     bouncy_bricks[i].draw();
 
-  for (unsigned int i = 0; i < bad_guys.size(); ++i)
-    bad_guys[i]->draw();
+  for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
+    (*i)->draw();
 
   tux.draw();
 
@@ -244,8 +243,8 @@ World::action(double frame_ratio)
   for (unsigned int i = 0; i < upgrades.size(); i++)
     upgrades[i].action(frame_ratio);
 
-  for (unsigned int i = 0; i < bad_guys.size(); i++)
-    bad_guys[i]->action(frame_ratio);
+  for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
+    (*i)->action(frame_ratio);
 
   /* update particle systems */
   std::vector<ParticleSystem*>::iterator p;
@@ -256,26 +255,33 @@ World::action(double frame_ratio)
 
   /* Handle all possible collisions. */
   collision_handler();
+  
+  { // Cleanup marked badguys
+    for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
+      if ((*i)->is_removable())
+        delete *i;
+    bad_guys.remove_if(std::mem_fun(&BadGuy::is_removable));
+  }
 }
 
-
 void
 World::collision_handler()
 {
   // CO_BULLET & CO_BADGUY check
   for(unsigned int i = 0; i < bullets.size(); ++i)
     {
-      for(unsigned int j = 0; j < bad_guys.size(); ++j)
+      for (BadGuys::iterator j = bad_guys.begin(); j != bad_guys.end(); ++j)
         {
-          if(bad_guys[j]->dying != DYING_NOT)
+          if((*j)->dying != DYING_NOT)
             continue;
-          if(rectcollision(&bullets[i].base, &bad_guys[j]->base))
+          
+          if(rectcollision(bullets[i].base, (*j)->base))
             {
               // We have detected a collision and now call the
               // collision functions of the collided objects.
               // collide with bad_guy first, since bullet_collision will
               // delete the bullet
-              bad_guys[j]->collision(0, CO_BULLET);
+              (*j)->collision(0, CO_BULLET);
               bullets[i].collision(CO_BADGUY);
               break; // bullet is invalid now, so break
             }
@@ -283,22 +289,24 @@ World::collision_handler()
     }
 
   /* CO_BADGUY & CO_BADGUY check */
-  for(unsigned int i = 0; i < bad_guys.size(); ++i)
+  for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
     {
-      if(bad_guys[i]->dying != DYING_NOT)
+      if((*i)->dying != DYING_NOT)
         continue;
       
-      for(unsigned int j = i+1; j < bad_guys.size(); ++j)
+      BadGuys::iterator j = i;
+      ++j;
+      for (; j != bad_guys.end(); ++j)
         {
-          if(j == i || bad_guys[j]->dying != DYING_NOT)
+          if(j == i || (*j)->dying != DYING_NOT)
             continue;
 
-          if(rectcollision(&bad_guys[i]->base, &bad_guys[j]->base))
+          if(rectcollision((*i)->base, (*j)->base))
             {
               // We have detected a collision and now call the
               // collision functions of the collided objects.
-              bad_guys[j]->collision(&bad_guys[i], CO_BADGUY);
-              bad_guys[i]->collision(&bad_guys[j], CO_BADGUY);
+              (*j)->collision(*i, CO_BADGUY);
+              (*i)->collision(*j, CO_BADGUY);
             }
         }
     }
@@ -306,25 +314,25 @@ World::collision_handler()
   if(tux.dying != DYING_NOT) return;
     
   // CO_BADGUY & CO_PLAYER check 
-  for(unsigned int i = 0; i < bad_guys.size(); ++i)
+  for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
     {
-      if(bad_guys[i]->dying != DYING_NOT)
+      if((*i)->dying != DYING_NOT)
         continue;
       
-      if(rectcollision_offset(&bad_guys[i]->base,&tux.base,0,0))
+      if(rectcollision_offset((*i)->base, tux.base, 0, 0))
         {
           // We have detected a collision and now call the collision
           // functions of the collided objects.
           if (tux.previous_base.y < tux.base.y &&
               tux.previous_base.y + tux.previous_base.height 
-              < bad_guys[i]->base.y + bad_guys[i]->base.height/2)
+              < (*i)->base.y + (*i)->base.height/2)
             {
-              bad_guys[i]->collision(&tux, CO_PLAYER, COLLISION_SQUISH);
+              (*i)->collision(&tux, CO_PLAYER, COLLISION_SQUISH);
             }
           else
             {
-              tux.collision(&bad_guys[i], CO_BADGUY);
-              bad_guys[i]->collision(&tux, CO_PLAYER, COLLISION_NORMAL);
+              tux.collision(*i, CO_BADGUY);
+              (*i)->collision(&tux, CO_PLAYER, COLLISION_NORMAL);
             }
         }
     }
@@ -332,7 +340,7 @@ World::collision_handler()
   // CO_UPGRADE & CO_PLAYER check
   for(unsigned int i = 0; i < upgrades.size(); ++i)
     {
-      if(rectcollision(&upgrades[i].base, &tux.base))
+      if(rectcollision(upgrades[i].base, tux.base))
         {
           // We have detected a collision and now call the collision
           // functions of the collided objects.
@@ -388,26 +396,9 @@ World::add_bouncy_brick(float x, float y)
 BadGuy*
 World::add_bad_guy(float x, float y, BadGuyKind kind, bool stay_on_platform)
 {
-  bad_guys.push_back(new BadGuy());
-  BadGuy* new_bad_guy = bad_guys.back();
-  
-  new_bad_guy->init(x,y,kind, stay_on_platform);
-  return new_bad_guy;
-}
-
-void
-World::remove_bad_guy(BadGuy* badguy)
-{
-  for(std::vector<BadGuy*>::iterator i = bad_guys.begin(); 
-      i != bad_guys.end(); ++i) 
-    {
-      if(*i == badguy)
-        {
-          World::current()->bad_guys.erase(i);
-          delete badguy;
-          return;
-        }
-    }
+  BadGuy* badguy = new BadGuy(x,y,kind, stay_on_platform);
+  bad_guys.push_back(badguy);
+  return badguy;
 }
 
 void
@@ -576,12 +567,12 @@ void
 World::trybumpbadguy(float x, float y)
 {
   // Bad guys: 
-  for (unsigned int i = 0; i < bad_guys.size(); i++)
+  for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
     {
-      if (bad_guys[i]->base.x >= x - 32 && bad_guys[i]->base.x <= x + 32 &&
-          bad_guys[i]->base.y >= y - 16 && bad_guys[i]->base.y <= y + 16)
+      if ((*i)->base.x >= x - 32 && (*i)->base.x <= x + 32 &&
+          (*i)->base.y >= y - 16 && (*i)->base.y <= y + 16)
         {
-          bad_guys[i]->collision(&tux, CO_PLAYER, COLLISION_BUMP);
+          (*i)->collision(&tux, CO_PLAYER, COLLISION_BUMP);
         }
     }
 
index d7b8e97..b87a257 100644 (file)
@@ -38,7 +38,9 @@ class Level;
 class World
 {
 private:
-  std::vector<BadGuy*> bad_guys;
+  typedef std::list<BadGuy*> BadGuys;
+  BadGuys bad_guys;
+  BadGuys bad_guys_to_add;
   Level* level;
   Player tux;
 
@@ -93,7 +95,6 @@ public:
   void add_bouncy_brick(float x, float y);
 
   BadGuy* add_bad_guy(float x, float y, BadGuyKind kind, bool stay_on_platform = false);
-  void    remove_bad_guy(BadGuy* badguy);
 
   void add_upgrade(float x, float y, Direction dir, UpgradeKind kind);
   void add_bullet(float x, float y, float xm, Direction dir);