-converted remaining classes to GameObject
[supertux.git] / src / badguy.cpp
index 6497e7e..1f626a6 100644 (file)
@@ -33,6 +33,8 @@
 #include "resources.h"
 #include "sprite_manager.h"
 #include "gameloop.h"
+#include "display_manager.h"
+#include "lispwriter.h"
 
 Sprite* img_mriceblock_flat_left;
 Sprite* img_mriceblock_flat_right;
@@ -142,20 +144,52 @@ std::string badguykind_to_string(BadGuyKind kind)
     }
 }
 
-BadGuy::BadGuy(float x, float y, BadGuyKind kind_, bool stay_on_platform_)
+BadGuy::BadGuy(DisplayManager& display_manager, BadGuyKind kind_,
+    LispReader& lispreader)
   : removable(false), squishcount(0)
 {
-  base.x   = x;
-  base.y   = y;    
+  display_manager.add_drawable(this, LAYER_OBJECTS);
+
+  base.x = 0;
+  base.y = 0;
+  lispreader.read_float("x", &base.x);
+  lispreader.read_float("y", &base.y);
+  base.width  = 0;
+  base.height = 0;
+
+  kind     = kind_;
+
+  stay_on_platform = false;
+  lispreader.read_bool("stay-on-platform", &stay_on_platform);  
+
+  init();
+}
+
+BadGuy::BadGuy(DisplayManager& display_manager, BadGuyKind kind_,
+    float x, float y)
+{
+  display_manager.add_drawable(this, LAYER_OBJECTS);
+
+  base.x = x;
+  base.y = y;
   base.width  = 0;
   base.height = 0;
-  base.xm  = 0;
-  base.ym  = 0;
+  stay_on_platform = false;
+
+  kind     = kind_;
+  
+  init();
+}
 
-  stay_on_platform = stay_on_platform_;
+BadGuy::~BadGuy()
+{
+}
+
+void
+BadGuy::init()
+{
   mode     = NORMAL;
   dying    = DYING_NOT;
-  kind     = kind_;
   old_base = base;
   dir      = LEFT;
   seen     = false;
@@ -178,7 +212,7 @@ BadGuy::BadGuy(float x, float y, BadGuyKind kind_, bool stay_on_platform_)
     // hack so that the bomb doesn't hurt until it expldes...
     dying = DYING_SQUISHED;
   } else if(kind == BAD_FLAME) {
-    base.ym = 0; // we misuse base.ym as angle for the flame
+    angle = 0;
     physic.enable_gravity(false);
     set_sprite(img_flame, img_flame);
   } else if(kind == BAD_BOUNCINGSNOWBALL) {
@@ -212,7 +246,19 @@ BadGuy::BadGuy(float x, float y, BadGuyKind kind_, bool stay_on_platform_)
 }
 
 void
-BadGuy::action_mriceblock(double frame_ratio)
+BadGuy::write(LispWriter& writer)
+{
+  writer.start_list(badguykind_to_string(kind));
+
+  writer.write_float("x", base.x);
+  writer.write_float("y", base.y);
+  writer.write_bool("stay-on-platform", stay_on_platform);  
+
+  writer.end_list(badguykind_to_string(kind));
+}
+
+void
+BadGuy::action_mriceblock(double elapsed_time)
 {
   Player& tux = *World::current()->get_tux();
 
@@ -223,7 +269,7 @@ BadGuy::action_mriceblock(double frame_ratio)
   if (mode != HELD)
     {
       // move
-      physic.apply(frame_ratio, base.x, base.y);
+      physic.apply(elapsed_time, base.x, base.y);
       if (dying != DYING_FALLING)
         collision_swept_object_map(&old_base,&base);
     }
@@ -383,13 +429,7 @@ BadGuy::fall()
 }
 
 void
-BadGuy::remove_me()
-{
-  removable = true;
-}
-
-void
-BadGuy::action_jumpy(double frame_ratio)
+BadGuy::action_jumpy(double elapsed_time)
 {
   if(frozen_timer.check())
     {
@@ -432,13 +472,13 @@ BadGuy::action_jumpy(double frame_ratio)
     dir = LEFT;
 
   // move
-  physic.apply(frame_ratio, base.x, base.y);
+  physic.apply(elapsed_time, base.x, base.y);
   if(dying == DYING_NOT)
     collision_swept_object_map(&old_base, &base);
 }
 
 void
-BadGuy::action_mrbomb(double frame_ratio)
+BadGuy::action_mrbomb(double elapsed_time)
 {
   if(frozen_timer.check())
     {
@@ -451,13 +491,13 @@ BadGuy::action_mrbomb(double frame_ratio)
 
   fall();
 
-  physic.apply(frame_ratio, base.x, base.y);
+  physic.apply(elapsed_time, base.x, base.y);
   if (dying != DYING_FALLING)
     collision_swept_object_map(&old_base,&base); 
 }
 
 void
-BadGuy::action_bomb(double frame_ratio)
+BadGuy::action_bomb(double elapsed_time)
 {
   static const int TICKINGTIME = 1000;
   static const int EXPLODETIME = 1000;
@@ -489,12 +529,12 @@ BadGuy::action_bomb(double frame_ratio)
   }
 
   // move
-  physic.apply(frame_ratio, base.x, base.y);                 
+  physic.apply(elapsed_time, base.x, base.y);                 
   collision_swept_object_map(&old_base,&base);
 }
 
 void
-BadGuy::action_stalactite(double frame_ratio)
+BadGuy::action_stalactite(double elapsed_time)
 {
   Player& tux = *World::current()->get_tux();
 
@@ -529,25 +569,25 @@ BadGuy::action_stalactite(double frame_ratio)
   }
 
   // move
-  physic.apply(frame_ratio, base.x, base.y);
+  physic.apply(elapsed_time, base.x, base.y);
 
   if(dying == DYING_SQUISHED && !timer.check())
     remove_me();
 }
 
 void
-BadGuy::action_flame(double frame_ratio)
+BadGuy::action_flame(double elapsed_time)
 {
     static const float radius = 100;
     static const float speed = 0.02;
-    base.x = old_base.x + cos(base.ym) * radius;
-    base.y = old_base.y + sin(base.ym) * radius;
+    base.x = old_base.x + cos(angle) * radius;
+    base.y = old_base.y + sin(angle) * radius;
 
-    base.ym = fmodf(base.ym + frame_ratio * speed, 2*M_PI);
+    angle = fmodf(angle + elapsed_time * speed, 2*M_PI);
 }
 
 void
-BadGuy::action_fish(double frame_ratio)
+BadGuy::action_fish(double elapsed_time)
 {
   if(frozen_timer.check())
     {
@@ -581,7 +621,7 @@ BadGuy::action_fish(double frame_ratio)
       physic.enable_gravity(true);
     }
 
-  physic.apply(frame_ratio, base.x, base.y);
+  physic.apply(elapsed_time, base.x, base.y);
   if(dying == DYING_NOT)
     collision_swept_object_map(&old_base, &base);
 
@@ -590,7 +630,7 @@ BadGuy::action_fish(double frame_ratio)
 }
 
 void
-BadGuy::action_bouncingsnowball(double frame_ratio)
+BadGuy::action_bouncingsnowball(double elapsed_time)
 {
   static const float JUMPV = 4.5;
     
@@ -610,7 +650,7 @@ BadGuy::action_bouncingsnowball(double frame_ratio)
   // check for right/left collisions
   check_horizontal_bump();
 
-  physic.apply(frame_ratio, base.x, base.y);
+  physic.apply(elapsed_time, base.x, base.y);
   if(dying == DYING_NOT)
     collision_swept_object_map(&old_base, &base);
 
@@ -624,7 +664,7 @@ BadGuy::action_bouncingsnowball(double frame_ratio)
 }
 
 void
-BadGuy::action_flyingsnowball(double frame_ratio)
+BadGuy::action_flyingsnowball(double elapsed_time)
 {
   static const float FLYINGSPEED = 1;
   static const int DIRCHANGETIME = 1000;
@@ -650,7 +690,7 @@ BadGuy::action_flyingsnowball(double frame_ratio)
   if(dying != DYING_NOT)
     physic.enable_gravity(true);
 
-  physic.apply(frame_ratio, base.x, base.y);
+  physic.apply(elapsed_time, base.x, base.y);
   if(dying == DYING_NOT || dying == DYING_SQUISHED)
     collision_swept_object_map(&old_base, &base);
 
@@ -664,7 +704,7 @@ BadGuy::action_flyingsnowball(double frame_ratio)
 }
 
 void
-BadGuy::action_spiky(double frame_ratio)
+BadGuy::action_spiky(double elapsed_time)
 {
   if(frozen_timer.check())
     {
@@ -685,26 +725,26 @@ BadGuy::action_spiky(double frame_ratio)
   }
 #endif
 
-  physic.apply(frame_ratio, base.x, base.y);
+  physic.apply(elapsed_time, base.x, base.y);
   if (dying != DYING_FALLING)
     collision_swept_object_map(&old_base,&base);   
 }
 
 void
-BadGuy::action_snowball(double frame_ratio)
+BadGuy::action_snowball(double elapsed_time)
 {
   if (dying == DYING_NOT)
     check_horizontal_bump();
 
   fall();
 
-  physic.apply(frame_ratio, base.x, base.y);
+  physic.apply(elapsed_time, base.x, base.y);
   if (dying != DYING_FALLING)
     collision_swept_object_map(&old_base,&base);
 }
 
 void
-BadGuy::action(double frame_ratio)
+BadGuy::action(float elapsed_time)
 {
   // Remove if it's far off the screen:
   if (base.x < scroll_x - OFFSCREEN_DISTANCE)
@@ -714,7 +754,7 @@ BadGuy::action(double frame_ratio)
     }
 
   // BadGuy fall below the ground
-  if (base.y > screen->h) {
+  if (base.y > World::current()->get_level()->height * 32) {
     remove_me();
     return;
   }
@@ -740,47 +780,47 @@ BadGuy::action(double frame_ratio)
   switch (kind)
     {
     case BAD_MRICEBLOCK:
-      action_mriceblock(frame_ratio);
+      action_mriceblock(elapsed_time);
       break;
   
     case BAD_JUMPY:
-      action_jumpy(frame_ratio);
+      action_jumpy(elapsed_time);
       break;
 
     case BAD_MRBOMB:
-      action_mrbomb(frame_ratio);
+      action_mrbomb(elapsed_time);
       break;
     
     case BAD_BOMB:
-      action_bomb(frame_ratio);
+      action_bomb(elapsed_time);
       break;
 
     case BAD_STALACTITE:
-      action_stalactite(frame_ratio);
+      action_stalactite(elapsed_time);
       break;
 
     case BAD_FLAME:
-      action_flame(frame_ratio);
+      action_flame(elapsed_time);
       break;
 
     case BAD_FISH:
-      action_fish(frame_ratio);
+      action_fish(elapsed_time);
       break;
 
     case BAD_BOUNCINGSNOWBALL:
-      action_bouncingsnowball(frame_ratio);
+      action_bouncingsnowball(elapsed_time);
       break;
 
     case BAD_FLYINGSNOWBALL:
-      action_flyingsnowball(frame_ratio);
+      action_flyingsnowball(elapsed_time);
       break;
 
     case BAD_SPIKY:
-      action_spiky(frame_ratio);
+      action_spiky(elapsed_time);
       break;
 
     case BAD_SNOWBALL:
-      action_snowball(frame_ratio);
+      action_snowball(elapsed_time);
       break;
     default:
       break;
@@ -788,8 +828,11 @@ BadGuy::action(double frame_ratio)
 }
 
 void
-BadGuy::draw()
+BadGuy::draw(ViewPort& viewport, int)
 {
+  float scroll_x = viewport.get_translation().x;
+  float scroll_y = viewport.get_translation().y;
+
   // Don't try to draw stuff that is outside of the screen
   if(base.x <= scroll_x - base.width || base.x >= scroll_x + screen->w)
     return;
@@ -800,7 +843,7 @@ BadGuy::draw()
     }
 
   Sprite* sprite = (dir == LEFT) ? sprite_left : sprite_right;
-  sprite->draw(base.x, base.y);
+  sprite->draw(viewport.world2screen(Vector(base.x, base.y)));
 
   if (debug_mode)
     fillrect(base.x - scroll_x, base.y - scroll_y, base.width, base.height, 75,0,75, 150);
@@ -864,8 +907,8 @@ BadGuy::squish_me(Player* player)
 {
   make_player_jump(player);
     
-  World::current()->add_score(base.x,
-                              base.y, 50 * player_status.score_multiplier);
+  World::current()->add_score(Vector(base.x, base.y),
+                              50 * player_status.score_multiplier);
   play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
   player_status.score_multiplier++;
 
@@ -881,13 +924,13 @@ BadGuy::squish(Player* player)
     
   if(kind == BAD_MRBOMB) {
     // mrbomb transforms into a bomb now
-    World::current()->add_bad_guy(base.x, base.y, BAD_BOMB);
+    explode();
     
     make_player_jump(player);
-    World::current()->add_score(base.x, base.y, 50 * player_status.score_multiplier);
+    World::current()->add_score(Vector(base.x, base.y),
+                                50 * player_status.score_multiplier);
     play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
     player_status.score_multiplier++;
-    remove_me();
     return;
 
   } else if (kind == BAD_MRICEBLOCK) {
@@ -936,7 +979,8 @@ BadGuy::squish(Player* player)
       
     make_player_jump(player);
              
-    World::current()->add_score(base.x, base.y, 25 * player_status.score_multiplier);
+    World::current()->add_score(Vector(base.x, base.y),
+                                25 * player_status.score_multiplier);
     player_status.score_multiplier++;
      
     // simply remove the fish...
@@ -977,17 +1021,24 @@ BadGuy::kill_me(int score)
 
   /* Gain some points: */
   if (score != 0)
-    World::current()->add_score(base.x, base.y,
-                    score * player_status.score_multiplier);
+    World::current()->add_score(Vector(base.x, base.y),
+                                score * player_status.score_multiplier);
 
   /* Play death sound: */
   play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
 }
 
-void BadGuy::explode(BadGuy *badguy)
+void
+BadGuy::explode()
+{
+  World::current()->add_bad_guy(base.x, base.y, BAD_BOMB);
+  remove_me();
+}
+
+void
+BadGuy::collision(const MovingObject&, int)
 {
-World::current()->add_bad_guy(badguy->base.x, badguy->base.y, BAD_BOMB);
-badguy->remove_me();
+  // later
 }
 
 void
@@ -1050,7 +1101,7 @@ BadGuy::collision(void *p_c_object, int c_object, CollisionType type)
         if (pbad_c->kind == BAD_MRBOMB)
         {
           // mrbomb transforms into a bomb now
-          explode(pbad_c);
+          pbad_c->explode();
           return;
         }
         else if (pbad_c->kind != BAD_MRBOMB)
@@ -1065,7 +1116,7 @@ BadGuy::collision(void *p_c_object, int c_object, CollisionType type)
         if (pbad_c->kind == BAD_MRBOMB)
         {
           // mrbomb transforms into a bomb now
-          explode(pbad_c);
+          pbad_c->explode();
           return;
         }
         else
@@ -1196,136 +1247,4 @@ void free_badguy_gfx()
 {
 }
 
-//---------------------------------------------------------------------------
-
-BadGuyManager::BadGuyManager()
-{
-  std::string filename = datadir + "/images/tilesets/supertux.stbg";
-  load_badguys(filename);
-}
-
-BadGuyManager::~BadGuyManager()
-{
-  for(std::vector<BadGuy*>::iterator i = badguys.begin(); i != badguys.end(); ++i) {
-    delete *i;                                                                  
-  }
-}
-
-void BadGuyManager::load_badguys(std::string filename)
-{
-/*
-  lisp_object_t* root_obj = lisp_read_from_file(filename);
-
-  if (!root_obj)
-    st_abort("Couldn't load file", filename);
-
-  if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-badguys") == 0)
-    {
-      lisp_object_t* cur = lisp_cdr(root_obj);
-
-      while(!lisp_nil_p(cur))
-        {
-          lisp_object_t* element = lisp_car(cur);
-
-          if (strcmp(lisp_symbol(lisp_car(element)), "badguy") == 0)
-            {
-             
-            
-              Tile* tile = new Tile;
-              tile->id      = -1;
-              tile->solid   = false;
-              tile->brick   = false;
-              tile->ice     = false;
-              tile->water   = false;
-              tile->fullbox = false;
-              tile->distro  = false;
-              tile->goal    = false;
-              tile->data    = 0;
-              tile->next_tile  = 0;
-              tile->anim_speed = 25;
-
-              LispReader reader(lisp_cdr(element));
-              assert(reader.read_int("id",  &tile->id));
-              reader.read_bool("solid",     &tile->solid);
-              reader.read_bool("brick",     &tile->brick);
-              reader.read_bool("ice",       &tile->ice);
-              reader.read_bool("water",     &tile->water);
-              reader.read_bool("fullbox",   &tile->fullbox);
-              reader.read_bool("distro",    &tile->distro);
-              reader.read_bool("goal",      &tile->goal);
-              reader.read_int("data",       &tile->data);
-              reader.read_int("anim-speed", &tile->anim_speed);
-              reader.read_int("next-tile",  &tile->next_tile);
-              reader.read_string_vector("images",  &tile->filenames);
-             reader.read_string_vector("editor-images", &tile->editor_filenames);
-
-              for(std::vector<std::string>::iterator it = tile->
-                  filenames.begin();
-                  it != tile->filenames.end();
-                  ++it)
-                {
-                  Surface* cur_image;
-                  tile->images.push_back(cur_image);
-                  tile->images[tile->images.size()-1] = new Surface(
-                               datadir +  "/images/tilesets/" + (*it),
-                               USE_ALPHA);
-                }
-              for(std::vector<std::string>::iterator it = tile->editor_filenames.begin();
-                  it != tile->editor_filenames.end();
-                  ++it)
-                {
-                  Surface* cur_image;
-                  tile->editor_images.push_back(cur_image);
-                  tile->editor_images[tile->editor_images.size()-1] = new Surface(
-                               datadir + "/images/tilesets/" + (*it),
-                               USE_ALPHA);
-                }
-               
-              if (tile->id + tileset_id >= int(tiles.size())
-                 )
-                tiles.resize(tile->id + tileset_id+1);
-
-              tiles[tile->id + tileset_id] = tile;
-            }
-          else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
-            {
-              LispReader reader(lisp_cdr(element));
-              std::string filename;
-              reader.read_string("file",  &filename);
-              filename = datadir + "/images/tilesets/" + filename;
-              load_tileset(filename);
-            }
-          else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
-            {
-              TileGroup new_;
-              LispReader reader(lisp_cdr(element));
-              reader.read_string("name",  &new_.name);
-              reader.read_int_vector("tiles", &new_.tiles);          
-              if(!tilegroups_)
-                tilegroups_ = new std::set<TileGroup>;
-              tilegroups_->insert(new_).first;
-            }
-          else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
-            {
-              LispReader reader(lisp_cdr(element));
-              reader.read_int("id",  &tileset_id);
-              tileset_id *= 1000;
-            }
-          else
-            {
-              puts("Unhandled symbol");
-            }
-
-          cur = lisp_cdr(cur);
-        }
-    }
-  else
-    {
-      assert(0);
-    }
-
-  lisp_free(root_obj);
-*/
-}
-
 // EOF //