merged bad_guy patch from Matze Braun. (recycling Ricardo's stalactite patch and...
authorTobias Gläßer <tobi.web@gmx.de>
Fri, 26 Mar 2004 23:53:31 +0000 (23:53 +0000)
committerTobias Gläßer <tobi.web@gmx.de>
Fri, 26 Mar 2004 23:53:31 +0000 (23:53 +0000)
SVN-Revision: 382

src/Makefile.am
src/badguy.cpp
src/badguy.h
src/collision.cpp
src/collision.h
src/gameloop.cpp
src/leveleditor.cpp
src/particlesystem.cpp
src/player.cpp
src/type.h

index 56d458a..19e60fe 100644 (file)
@@ -1,6 +1,6 @@
 bin_PROGRAMS = supertux
 
-supertux_SOURCES = badguy.cpp badguy.h bitmask.cpp bitmask.h button.cpp button.h collision.cpp collision.h configfile.cpp configfile.h defines.h gameloop.cpp gameloop.h globals.cpp globals.h high_scores.cpp high_scores.h intro.cpp intro.h level.cpp level.h leveleditor.cpp leveleditor.h lispreader.cpp lispreader.h menu.cpp menu.h particlesystem.cpp particlesystem.h physic.cpp physic.h player.cpp player.h scene.cpp scene.h screen.cpp screen.h setup.cpp setup.h sound.cpp sound.h special.cpp special.h supertux.cpp supertux.h text.cpp text.h texture.cpp texture.h timer.cpp timer.h title.cpp title.h type.cpp type.h world.cpp world.h worldmap.cpp worldmap.h tile.h tile.cpp
+supertux_SOURCES = badguy.cpp badguy.h bitmask.cpp bitmask.h button.cpp button.h collision.cpp collision.h configfile.cpp configfile.h defines.h gameloop.cpp gameloop.h globals.cpp globals.h high_scores.cpp high_scores.h intro.cpp intro.h level.cpp level.h leveleditor.cpp leveleditor.h lispreader.cpp lispreader.h menu.cpp menu.h particlesystem.cpp particlesystem.h physic.cpp physic.h player.cpp player.h scene.cpp scene.h screen.cpp screen.h setup.cpp setup.h sound.cpp sound.h special.cpp special.h supertux.cpp supertux.h text.cpp text.h texture.cpp texture.h timer.cpp timer.h title.cpp title.h type.cpp type.h world.cpp world.h worldmap.cpp worldmap.h tile.h tile.cpp mousecursor.cpp mousecursor.h
 
 # EOF #
 noinst_HEADERS = 
index 2b603a4..611ddcf 100644 (file)
@@ -30,6 +30,10 @@ texture_type img_laptop_left[3];
 texture_type img_laptop_right[3];
 texture_type img_money_left[2];
 texture_type img_money_right[2];
+texture_type img_mrbomb_left[4];
+texture_type img_mrbomb_right[4];
+texture_type img_stalactite;
+texture_type img_stalactite_broken;
 
 BadGuyKind  badguykind_from_string(const std::string& str)
 {
@@ -39,6 +43,10 @@ BadGuyKind  badguykind_from_string(const std::string& str)
     return BAD_LAPTOP;
   else if (str == "bsod")
     return BAD_BSOD;
+  else if (str == "mrbomb")
+    return BAD_MRBOMB;
+  else if (str == "stalactite")
+    return BAD_STALACTITE;
   else
     {
       printf("Couldn't convert badguy: %s\n", str.c_str());
@@ -59,6 +67,12 @@ std::string badguykind_to_string(BadGuyKind kind)
     case BAD_BSOD:
       return "bsod";
       break;
+    case BAD_MRBOMB:
+      return "mrbomb";
+      break;
+    case BAD_STALACTITE:
+      return "stalactite";
+      break;
     default:
       return "bsod";
     }
@@ -74,13 +88,20 @@ BadGuy::init(float x, float y, BadGuyKind kind_)
   kind     = kind_;
   base.x   = x;
   base.y   = y;
-  base.xm  = 1.3;
+  base.xm  = -1.3;
   base.ym  = 4.8;
   old_base = base;
   dir      = LEFT;
   seen     = false;
   timer_init(&timer, true);
   physic_init(&physic);
+
+  if(kind == BAD_BOMB) {
+    timer_start(&timer, 1000);
+    mode = BOMB_TICKING;
+    // hack so that the bomb doesn't hurt until it expldes...
+    dying = DYING_SQUISHED;
+  }
 }
 
 void BadGuy::action_bsod()
@@ -91,10 +112,7 @@ void BadGuy::action_bsod()
   if (dying == DYING_NOT ||
       dying == DYING_FALLING)
     {
-      if (dir == RIGHT)
-        base.x = base.x + base.xm * frame_ratio;
-      else if (dir == LEFT)
-        base.x = base.x - base.xm * frame_ratio;
+      base.x += base.xm * frame_ratio;
     }
 
   /* Move vertically: */
@@ -102,61 +120,21 @@ void BadGuy::action_bsod()
 
   if (dying != DYING_FALLING)
     collision_swept_object_map(&old_base,&base);
-  if (base.y > screen->h)
-    bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(this));
                
-  /* Bump into things horizontally: */
-
   if (!dying)
-    {
-      if (issolid( base.x, (int) base.y + 16))
-        {
-          dir = RIGHT;
-        }
-      else if (issolid( base.x + base.width, (int) base.y + 16))
-        {
-          dir = LEFT;
-        }
-    }
-
-  /* Fall if we get off the ground: */
-  if (dying != DYING_FALLING)
-    {
-      if (!issolid(base.x+16, base.y + 32))
-        {
-          if(!physic_is_set(&physic))
-            {
-              physic_set_state(&physic,PH_VT);
-              physic_set_start_vy(&physic,2.);
-            }
+    check_horizontal_bump();
 
-          base.ym = physic_get_velocity(&physic);
-        }
-      else
-        {
-          /* Land: */
+  fall();
 
-          if (base.ym > 0)
-            {
-              base.y = (int)(base.y / 32) * 32;
-              base.ym = 0;
-            }
-          physic_init(&physic);
-        }
-    }
-  else
+  // Handle dying timer:
+  if (dying == DYING_SQUISHED)       
     {
-      if(!physic_is_set(&physic))
-        {
-          physic_set_state(&physic,PH_VT);
-          physic_set_start_vy(&physic,2.);
-        }
-      base.ym = physic_get_velocity(&physic);
+      /* Remove it if time's up: */
+      if(!timer_check(&timer)) {
+        remove_me();
+        return;
+      }
     }
-
-  // BadGuy fall below the ground
-  if (base.y > screen->h)
-    bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(this));
 }
 
 void BadGuy::action_laptop()
@@ -167,10 +145,7 @@ void BadGuy::action_laptop()
       if (dying == DYING_NOT ||
           dying == DYING_FALLING)
         {
-          if (dir == RIGHT)
-            base.x = base.x + base.xm * frame_ratio;
-          else if (dir == LEFT)
-            base.x = base.x - base.xm * frame_ratio;
+          base.x += base.xm * frame_ratio;
         }
     }
   else if (mode == HELD)
@@ -214,37 +189,79 @@ void BadGuy::action_laptop()
 
   if (dying != DYING_FALLING)
     collision_swept_object_map(&old_base,&base);
-  if (base.y > screen->h)
-    bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(this));
-  /* Bump into things horizontally: */
-
   /* Bump into things horizontally: */
 
   if (!dying)
     {
       int changed = dir;
-      if (issolid( base.x, (int) base.y + 16))
-        {
-          dir = RIGHT;
-        }
-      else if (issolid( base.x + base.width, (int) base.y + 16))
-        {
-          dir = LEFT;
-        }
+      check_horizontal_bump();
       if(mode == KICK && changed != dir)
         {
-          /* handle stereo sound */
-          /* FIXME: In theory a badguy object doesn't know anything about player objects */
-          if (tux.base.x  > base.x)
+          /* handle stereo sound (number 10 should be tweaked...)*/
+          if (base.x < scroll_x - 10)
             play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
-          else if (tux.base.x  < base.x)
+          else if (base.x > scroll_x + 10)
             play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
           else
             play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
         }
+    }
+
+  fall();
 
+  /* Handle mode timer: */
+  if (mode == FLAT && mode != HELD)
+    {
+      if(!timer_check(&timer))
+        {
+          mode = NORMAL;
+          base.xm = 4;
+        }
+    }
+  else if (mode == KICK)
+    {
+      timer_check(&timer);
     }
+}
 
+void BadGuy::check_horizontal_bump(bool checkcliff)
+{
+    if (dir == LEFT && issolid( base.x, (int) base.y + 16))
+    {
+        dir = RIGHT;
+        base.xm = -base.xm;
+        return;
+    }
+    if (dir == RIGHT && issolid( base.x + base.width, (int) base.y + 16))
+    {
+        dir = LEFT;
+        base.xm = -base.xm;
+        return;
+    }
+
+    // don't check for cliffs when we're falling
+    if(!checkcliff)
+        return;
+    
+    if(dir == LEFT && !issolid(base.x, (int) base.y + base.height + 16))
+    {
+        printf("Cliffcol left\n");
+        dir = RIGHT;
+        base.xm = -base.xm;
+        return;
+    }
+    if(dir == RIGHT && !issolid(base.x + base.width,
+                (int) base.y + base.height + 16))
+    {
+        printf("Cliffcol right\n");
+        dir = LEFT;
+        base.xm = -base.xm;
+        return;
+    }
+}
+
+void BadGuy::fall()
+{
   /* Fall if we get off the ground: */
   if (dying != DYING_FALLING)
     {
@@ -276,12 +293,29 @@ void BadGuy::action_laptop()
   else
     {
       if(!physic_is_set(&physic))
-        {
+        {                                                
           physic_set_state(&physic,PH_VT);
           physic_set_start_vy(&physic,0.);
         }
       base.ym = physic_get_velocity(&physic);
     }
+
+  // BadGuy fall below the ground
+  if (base.y > screen->h) {
+    remove_me();
+    return;
+  }
+}
+
+void BadGuy::remove_me()
+{
+  std::vector<BadGuy>::iterator i;
+  for(i = bad_guys.begin(); i != bad_guys.end(); ++i) {
+    if( & (*i) == this) {
+      bad_guys.erase(i);
+      return;
+    }
+  }
 }
 
 void BadGuy::action_money()
@@ -292,8 +326,10 @@ void BadGuy::action_money()
   if (dying != DYING_FALLING)
     collision_swept_object_map(&old_base,&base);
 
-  if (base.y > screen->h)
-    bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(this));
+  if (base.y > screen->h) {
+    remove_me();
+    return;
+  }
 
   if(physic_get_state(&physic) == -1)
     {
@@ -303,19 +339,21 @@ void BadGuy::action_money()
 
   if (dying != DYING_FALLING)
     {
+      
       if(issolid(base.x, base.y + 32))
         {
           physic_set_state(&physic,PH_VT);
           physic_set_start_vy(&physic,6.);
           base.ym = physic_get_velocity(&physic);
         }
+      /* // matze: is this code needed?
       else if(issolid(base.x, base.y))
-        { /* This works, but isn't the best solution imagineable */
+        { // This works, but isn't the best solution imagineable 
           physic_set_state(&physic,PH_VT);
           physic_set_start_vy(&physic,0.);
           base.ym = physic_get_velocity(&physic);
           ++base.y;
-        }
+        }*/
       else
         {
           base.ym = physic_get_velocity(&physic);
@@ -332,6 +370,65 @@ void BadGuy::action_money()
     } 
 }
 
+void BadGuy::action_mrbomb()
+{
+  if(mode == NORMAL) {
+    base.x += base.xm * frame_ratio;
+  }
+
+  /* Move vertically: */
+  base.y += base.ym * frame_ratio;
+
+  if (dying != DYING_FALLING)
+    collision_swept_object_map(&old_base,&base);
+
+  check_horizontal_bump(true);
+  fall();
+}
+
+void BadGuy::action_bomb()
+{
+  // eventually fall down
+  base.y += base.ym * frame_ratio;
+  collision_swept_object_map(&old_base,&base);
+  fall();
+
+  if(!timer_check(&timer)) {
+    if(mode == BOMB_TICKING) {
+      mode = BOMB_EXPLODE;
+      dying = DYING_NOT; // now the bomb hurts
+      timer_start(&timer, 1000);
+    } else if(mode == BOMB_EXPLODE) {
+      remove_me();
+      return;
+    }
+  }
+}
+
+void BadGuy::action_stalactite()
+{
+  if(mode == NORMAL) {
+    if(tux.base.x + 32 > base.x - 40 && tux.base.x < base.x + 32 + 40) {
+      timer_start(&timer, 800);
+      mode = STALACTITE_SHAKING;
+    }
+  } if(mode == STALACTITE_SHAKING) {
+    base.x = old_base.x + (rand() % 6) - 3; // TODO this could be done nicer...
+    if(!timer_check(&timer)) {
+      mode = STALACTITE_FALL;
+    }
+  } else if(mode == STALACTITE_FALL) {
+    base.y += base.ym * frame_ratio;   
+    /* Destroy if collides land */
+    if(issolid(base.x+16, base.y+32))
+    {
+      timer_start(&timer, 3000);
+      dying = DYING_SQUISHED;
+      mode = FLAT;
+    }
+  }
+}
+
 void
 BadGuy::action()
 { 
@@ -344,41 +441,32 @@ BadGuy::action()
           break;
     
         case BAD_LAPTOP:
-          action_bsod();
+          action_laptop();
           break;
       
         case BAD_MONEY:
           action_money();
           break;
-        }
-    }
 
-  /* Handle mode timer: */
-  if (mode == FLAT && mode != HELD)
-    {
-      if(!timer_check(&timer))
-        {
-          mode = NORMAL;
-          base.xm = 4;
-        }
-    }
-  else if (mode == KICK)
-    {
-      timer_check(&timer);
-    }
+        case BAD_MRBOMB:
+          action_mrbomb();
+          break;
+        
+        case BAD_BOMB:
+          action_bomb();
+          break;
 
-  // Handle dying timer:
-  if (dying == DYING_SQUISHED)
-    {
-      /* Remove it if time's up: */
-      if(!timer_check(&timer))
-        bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(this));
+        case BAD_STALACTITE:
+          action_stalactite();
+          break;
+
+        }
     }
 
   // Remove if it's far off the screen:
   if (base.x < scroll_x - OFFSCREEN_DISTANCE)
     {
-      bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(this));
+      remove_me();
       return;
     }
   else /* !seen */
@@ -392,154 +480,103 @@ BadGuy::action()
 void
 BadGuy::draw_bsod()
 {
-  /* --- BLUE SCREEN OF DEATH MONSTER: --- */
-  if (dying == DYING_NOT)
-    {
-      /* Alive: */
-      if (dir == LEFT)
-        {
-          texture_draw(&img_bsod_left[(global_frame_counter / 5) % 4],
-                       base.x - scroll_x,
-                       base.y);
-        }
-      else
-        {
-          texture_draw(&img_bsod_right[(global_frame_counter / 5) % 4],
-                       base.x - scroll_x,
-                       base.y);
-        }
-    }
-  else if (dying == DYING_FALLING)
-    {
-      /* Falling: */
+  texture_type* texture = 0;
+  float y = base.y;
+  if(dying == DYING_NOT) {
+    size_t frame = (global_frame_counter / 5) % 4;
+    texture = (dir == LEFT) ? &img_bsod_left[frame] : &img_bsod_right[frame];
+  } else if(dying == DYING_FALLING) {
+    texture = (dir == LEFT) ? &img_bsod_falling_left : &img_bsod_falling_right;
+  } else if(dying == DYING_SQUISHED) {
+    texture = (dir == LEFT) 
+        ? &img_bsod_squished_left : &img_bsod_squished_right;
+    y += 24;
+  }
+  
+  texture_draw(texture, base.x - scroll_x, y);
+}
 
-      if (dir == LEFT)
-        {
-          texture_draw(&img_bsod_falling_left,
-                       base.x - scroll_x,
-                       base.y);
-        }
+void
+BadGuy::draw_laptop()
+{
+  texture_type* texture;
+  size_t frame = (global_frame_counter / 5) % 3;
+  
+  if(dying == DYING_NOT) {
+    if(mode == NORMAL) {
+      if(dir == LEFT)
+        texture = &img_laptop_left[frame];
       else
-        {
-          texture_draw(&img_bsod_falling_right,
-                       base.x - scroll_x,
-                       base.y);
-        }
+        texture = &img_laptop_right[frame];
+    } else {
+      texture = (dir == LEFT) ? &img_laptop_flat_left : &img_laptop_flat_right;
     }
-  else if (dying == DYING_SQUISHED)
-    {
-      /* Dying - Squished: */
+  } else {
+    texture = (dir == LEFT) 
+        ? &img_laptop_falling_left : &img_laptop_falling_right;
+  }
 
-      if (dir == LEFT)
-        {
-          texture_draw(&img_bsod_squished_left,
-                       base.x - scroll_x,
-                       base.y + 24);
-        }
-      else
-        {
-          texture_draw(&img_bsod_squished_right,
-                       base.x - scroll_x,
-                       base.y + 24);
-        }
-    }
+  texture_draw(texture, base.x - scroll_x, base.y);
 }
 
-void BadGuy::draw_laptop()
+void
+BadGuy::draw_money()
 {
-  /* --- LAPTOP MONSTER: --- */
-  if (dying == DYING_NOT)
-    {
-      /* Alive: */
+  texture_type* texture;
+  size_t frame = (base.ym != 300) ? 0 : 1;
 
-      if (mode == NORMAL)
-        {
-          /* Not flat: */
-          if (dir == LEFT)
-            {
-              texture_draw(&img_laptop_left[(global_frame_counter / 5) % 3],
-                           base.x - scroll_x,
-                           base.y);
-            }
-          else
-            {
-              texture_draw(&img_laptop_right[(global_frame_counter / 5) % 3],
-                           base.x - scroll_x,
-                           base.y);
-            }
-        }
-      else
-        {
-          /* Flat: */
+  if(tux.base.x + tux.base.width < base.x) {
+    texture = &img_money_left[frame];
+  } else {
+    texture = &img_money_right[frame];
+  }
 
-          if (dir == LEFT)
-            {
-              texture_draw(&img_laptop_flat_left,
-                           base.x - scroll_x,
-                           base.y);
-            }
-          else
-            {
-              texture_draw(&img_laptop_flat_right,
-                           base.x - scroll_x,
-                           base.y);
-            }
-        }
-    }
-  else if (dying == DYING_FALLING)
-    {
-      /* Falling: */
+  texture_draw(texture, base.x - scroll_x, base.y);
+}
+  
+void
+BadGuy::draw_mrbomb()
+{
+  texture_type* texture;
+  size_t frame = (global_frame_counter/5) % 4;
 
-      if (dir == LEFT)
-        {
-          texture_draw(&img_laptop_falling_left,
-                       base.x - scroll_x,
-                       base.y);
-        }
-      else
-        {
-          texture_draw(&img_laptop_falling_right,
-                       base.x - scroll_x,
-                       base.y);
-        }
-    }
+  if(dir == LEFT)
+    texture = &img_mrbomb_left[frame];
+  else
+    texture = &img_mrbomb_right[frame];
+
+  texture_draw(texture, base.x - scroll_x, base.y);
 }
 
-void BadGuy::draw_money()
+void
+BadGuy::draw_bomb()
 {
-  if (base.ym != 300 /* > -16*/)
-    {
-      if (dir == LEFT)
-        {
-          texture_draw(&img_money_left[0],
-                       base.x - scroll_x,
-                       base.y);
-        }
-      else
-        {
-          texture_draw(&img_money_right[0],
-                       base.x - scroll_x,
-                       base.y);
-        }
-    }
+  texture_type* texture;
+  
+  // TODO add real bomb graphics
+  if(mode == BOMB_TICKING) {
+    texture = &img_bsod_squished_right;
+  } else {
+    texture = &img_bsod_squished_left;
+  }
+  
+  texture_draw(texture, base.x - scroll_x, base.y);
+}
+
+void
+BadGuy::draw_stalactite()
+{
+  texture_type* texture;
+  if(mode != FLAT)
+    texture = &img_stalactite;
   else
-    {
-      if (dir == LEFT)
-        {
-          texture_draw(&img_money_left[1],
-                       base.x - scroll_x,
-                       base.y);
-        }
-      else
-        {
-          texture_draw(&img_money_right[1],
-                       base.x - scroll_x,
-                       base.y);
-        }
-    }
+    texture = &img_stalactite_broken;
+
+  texture_draw(texture, base.x - scroll_x, base.y);
 }
 
-void BadGuy::draw()
+void
+BadGuy::draw()
 {
   // Don't try to draw stuff that is outside of the screen
   if (base.x > scroll_x - 32 &&
@@ -559,22 +596,120 @@ void BadGuy::draw()
           draw_money();
           break;
 
-        default:
-          puts("Unknown badguy type");
+        case BAD_MRBOMB:
+          draw_mrbomb();
+          break;
+
+        case BAD_BOMB:
+          draw_bomb();
+          break;
+
+        case BAD_STALACTITE:
+          draw_stalactite();
           break;
         }
     }
 }
 
 void
-BadGuy::collision(void *p_c_object, int c_object)
+BadGuy::bump()
+{
+  if(kind == BAD_BSOD || kind == BAD_LAPTOP || kind == BAD_BOMB) {
+    dying = DYING_FALLING;
+    base.ym = -8;
+    play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
+  }
+}
+
+void
+BadGuy::make_player_jump(Player* player)
+{
+    physic_set_state(&player->vphysic,PH_VT);
+    physic_set_start_vy(&player->vphysic,2.);
+    player->base.y = base.y - player->base.height - 1;
+}
+
+void
+BadGuy::squich(Player* player)
+{
+  if(kind == BAD_MRBOMB) {
+      // mrbomb transforms into a bomb now
+      add_bad_guy(base.x, base.y, BAD_BOMB);
+      
+      make_player_jump(player);
+      add_score(base.x - scroll_x, base.y, 50 * score_multiplier);
+      play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
+      score_multiplier++;
+      
+      remove_me();
+      return;
+
+  } else if(kind == BAD_BSOD) {
+      dying = DYING_SQUISHED;
+      timer_start(&timer,4000);
+
+      make_player_jump(player);
+
+      add_score(base.x - scroll_x, base.y, 50 * score_multiplier);
+      play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
+      score_multiplier++;
+      return;
+      
+  } else if (kind == BAD_LAPTOP) {
+      if (mode == NORMAL || mode == KICK)
+      {
+          /* Flatten! */
+          play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
+          mode = FLAT;
+          base.xm = 4;
+
+          timer_start(&timer, 4000);
+      } else if (mode == FLAT) {
+          /* Kick! */
+          play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
+
+          if (player->base.x < base.x + (base.width/2))
+              dir = RIGHT;
+          else
+              dir = LEFT;
+
+          base.xm = 5;
+          mode = KICK;
+
+          timer_start(&timer,5000);
+      }
+
+      make_player_jump(player);
+             
+      add_score(base.x - scroll_x,
+              base.y,
+              25 * score_multiplier);
+      score_multiplier++;
+      return;
+  }
+}
+
+void
+BadGuy::collision(void *p_c_object, int c_object, CollisionType type)
 {
   BadGuy* pbad_c    = NULL;
-  Player* pplayer_c = NULL;
+
+  if(type == COLLISION_BUMP) {
+    bump();
+    return;
+  }
+  if(type == COLLISION_SQUICH) {
+    Player* player = static_cast<Player*>(p_c_object);
+    squich(player);
+    return;
+  }
 
   switch (c_object)
     {
     case CO_BULLET:
+      if(kind == BAD_BOMB || kind == BAD_STALACTITE)
+        return;
+
       dying = DYING_FALLING;
       base.ym = -8;
 
@@ -619,72 +754,7 @@ BadGuy::collision(void *p_c_object, int c_object)
                     pbad_c->base.y, 100);
         }
       break;
-
-    case CO_PLAYER:
-      pplayer_c = static_cast<Player*>(p_c_object);
-      if(kind != BAD_MONEY)
-        {
-          if (kind == BAD_BSOD)
-            {
-              dying = DYING_SQUISHED;
-              timer_start(&timer,4000);
-              physic_set_state(&pplayer_c->vphysic,PH_VT);
-              physic_set_start_vy(&pplayer_c->vphysic,2.);
-             pplayer_c->base.y = base.y - pplayer_c->base.height - 1;
-
-              add_score(base.x - scroll_x, base.y,
-                        50 * score_multiplier);
-
-              play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
-            }
-          else if (kind == BAD_LAPTOP)
-            {
-
-              if (mode == NORMAL || mode == KICK)
-                {
-                  /* Flatten! */
-
-                  play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
-                  mode = FLAT;
-                  base.xm = 4;
-
-                  timer_start(&timer,10000);
-
-                  physic_set_state(&pplayer_c->vphysic,PH_VT);
-                  physic_set_start_vy(&pplayer_c->vphysic,2.);
-                 pplayer_c->base.y = base.y - pplayer_c->base.height - 1;
-                }
-              else if (mode == FLAT)
-                {
-                  /* Kick! */
-                  play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
-
-                  if (pplayer_c->base.x < base.x + (base.width/2))
-                    dir = RIGHT;
-                  else
-                    dir = LEFT;
-
-                  base.xm = 5;
-                 mode = KICK;
-
-                  timer_start(&timer,5000);
-                }
-               
-              physic_set_state(&pplayer_c->vphysic,PH_VT);
-              physic_set_start_vy(&pplayer_c->vphysic,2.);
-             pplayer_c->base.y = base.y - pplayer_c->base.height - 1;
-             
-              add_score(base.x - scroll_x,
-                        base.y,
-                        25 * score_multiplier);
-
-              /* play_sound(sounds[SND_SQUISH]); */
-            }
-          score_multiplier++;
-        }
-      break;
     }
-
 }
 
 // EOF //
index 6590fa6..ca4e16c 100644 (file)
 #include "collision.h"
 
 /* Enemy modes: */
-#define NORMAL 0
-#define FLAT 1
-#define KICK 2
-#define HELD 3
+enum {
+    NORMAL=0,
+    FLAT,
+    KICK,
+    HELD,
+
+    BOMB_TICKING,
+    BOMB_EXPLODE,
+
+    STALACTITE_SHAKING,
+    STALACTITE_FALL
+};
 
 extern texture_type img_bsod_squished_left;
 extern texture_type img_bsod_squished_right;
@@ -41,12 +49,19 @@ extern texture_type img_laptop_left[3];
 extern texture_type img_laptop_right[3];
 extern texture_type img_money_left[2];
 extern texture_type img_money_right[2];
+extern texture_type img_mrbomb_left[4];
+extern texture_type img_mrbomb_right[4];
+extern texture_type img_stalactite;
+extern texture_type img_stalactite_broken;
 
 /* Bad guy kinds: */
 enum BadGuyKind {
   BAD_BSOD,
   BAD_LAPTOP,
-  BAD_MONEY
+  BAD_MONEY,
+  BAD_MRBOMB,
+  BAD_BOMB,
+  BAD_STALACTITE
 };
 
 BadGuyKind  badguykind_from_string(const std::string& str);
@@ -65,6 +80,8 @@ struct BadGuyData
     : kind(BAD_BSOD), x(0), y(0) {}
 };
 
+class Player;
+
 /* Badguy type: */
 class BadGuy
 {
@@ -85,6 +102,13 @@ class BadGuy
   void action();
   void draw();
 
+  void collision(void* p_c_object, int c_object,
+          CollisionType type = COLLISION_NORMAL);
+  
+ private:
+  void fall();
+  void remove_me();
+
   void action_bsod();
   void draw_bsod();
 
@@ -94,7 +118,19 @@ class BadGuy
   void action_money(); 
   void draw_money();
 
-  void collision(void* p_c_object, int c_object);
+  void action_bomb();
+  void draw_bomb();
+
+  void action_mrbomb();
+  void draw_mrbomb();
+
+  void action_stalactite();
+  void draw_stalactite();
+
+  void make_player_jump(Player* player);
+  void check_horizontal_bump(bool checkcliff = false);
+  void bump();
+  void squich(Player* player);
 };
 
 #endif /*SUPERTUX_BADGUY_H*/
index afb4a92..117d6c7 100644 (file)
@@ -250,10 +250,9 @@ void collision_handler()
           // 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 &&
-              bad_guys[i].kind != BAD_MONEY && bad_guys[i].mode != HELD)
+              tux.previous_base.y + tux.previous_base.height < bad_guys[i].base.y + bad_guys[i].base.height/2)
             {
-              bad_guys[i].collision(&tux, CO_PLAYER);
+              bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_SQUICH);
             }
           else
             {
index 2105594..410e2e8 100644 (file)
@@ -19,10 +19,15 @@ enum
 {
   CO_BULLET,
   CO_BADGUY,
-  CO_BSOD,
   CO_PLAYER
 };
 
+enum CollisionType {
+    COLLISION_NORMAL,
+    COLLISION_BUMP,
+    COLLISION_SQUICH
+};
+
 bool rectcollision(base_type* one, base_type* two);
 bool rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y);
 void collision_swept_object_map(base_type* old, base_type* current);
index 03e8f6e..4a8d7f2 100644 (file)
@@ -110,7 +110,6 @@ void activate_bad_guys(void)
 
 void activate_particle_systems(void)
 {
-  printf("PSys: %s\n", current_level.particle_system.c_str());
   if(current_level.particle_system == "clouds")
     {
       particle_systems.push_back(new CloudParticleSystem);
@@ -1145,7 +1144,21 @@ void loadshared(void)
                "/images/shared/bag-right-1.png",
                USE_ALPHA);
 
+  /* Mr. Bomb */
+  for(int i=0; i<4; ++i) {
+      char num[4];
+      snprintf(num, 4, "%d", i);
+      texture_load(&img_mrbomb_left[i],
+              datadir + "/images/shared/mrbomb-left-" + num + ".png", USE_ALPHA);
+      texture_load(&img_mrbomb_right[i],
+              datadir + "/images/shared/mrbomb-right-" + num + ".png", USE_ALPHA);
+  }
 
+  /* stalactite */
+  texture_load(&img_stalactite, 
+          datadir + "/images/shared/stalactite.png", USE_ALPHA);
+  texture_load(&img_stalactite_broken,
+          datadir + "/images/shared/stalactite-broken.png", USE_ALPHA);
 
   /* Upgrades: */
 
@@ -1272,6 +1285,14 @@ void unloadshared(void)
       texture_free(&img_money_right[i]);
     }
 
+  for(i = 0; i < 4; i++) {
+      texture_free(&img_mrbomb_left[i]);
+      texture_free(&img_mrbomb_right[i]);
+  }
+
+  texture_free(&img_stalactite);
+  texture_free(&img_stalactite_broken);
+
   texture_free(&img_box_full);
   texture_free(&img_box_empty);
 
@@ -1625,13 +1646,7 @@ void trybumpbadguy(float x, float y)
       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 (bad_guys[i].kind == BAD_BSOD ||
-              bad_guys[i].kind == BAD_LAPTOP)
-            {
-              bad_guys[i].dying = DYING_FALLING;
-              bad_guys[i].base.ym = -8;
-              play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
-            }
+          bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_BUMP);
         }
     }
 
index 0cb0282..a7fc46f 100644 (file)
@@ -90,7 +90,7 @@ static int le_show_grid;
 static int le_frame;
 static texture_type le_selection;
 static int done;
-static char le_current_tile;
+static unsigned int le_current_tile;
 static bool le_mouse_pressed[2];
 static button_type le_save_level_bt;
 static button_type le_test_level_bt;
@@ -382,7 +382,7 @@ int le_init()
   le_level_changed = false;
   le_current_level = NULL;
 
-  le_current_tile = '.';
+  le_current_tile = 0;
   le_mouse_pressed[LEFT] = false;
   le_mouse_pressed[RIGHT] = false;
 
@@ -1086,7 +1086,7 @@ void le_checkevents()
                     }
                   button_event(&le_rubber_bt,&event);
                   if(button_get_state(&le_rubber_bt) == BUTTON_CLICKED)
-                    le_current_tile = '.';
+                    le_current_tile = 0;
                   button_event(&le_select_mode_one_bt,&event);
                   if(button_get_state(&le_select_mode_one_bt) == BUTTON_CLICKED)
                     le_selection_mode = CURSOR;
index db1ca26..2003024 100644 (file)
@@ -82,7 +82,10 @@ SnowParticleSystem::SnowParticleSystem()
         particle->layer = i % 2;
         int snowsize = rand() % 3;
         particle->texture = &snowimages[snowsize];
-        particle->speed = 0.01 + snowsize/50.0 + (rand()%(int)gravity/15.0);
+        do {
+            particle->speed = snowsize/60.0 + (float(rand()%10)/300.0);
+        } while(particle->speed < 0.01);
+        particle->speed *= gravity;
 
         particles.push_back(particle);
     }
@@ -111,13 +114,13 @@ CloudParticleSystem::CloudParticleSystem()
 {
     texture_load(&cloudimage, datadir + "/images/shared/cloud.png", USE_ALPHA);
 
-    virtual_width = 5000.0;
+    virtual_width = 2000.0;
 
     // create some random clouds
     for(size_t i=0; i<15; ++i) {
         CloudParticle* particle = new CloudParticle;
         particle->x = rand() % int(virtual_width);
-        particle->y = rand() % int((float) screen->h * 0.3333);
+        particle->y = rand() % int(virtual_height);
         particle->layer = 0;
         particle->texture = &cloudimage;
         particle->speed = -float(250 + rand() % 200) / 1000.0;
index 9f04006..f208844 100644 (file)
@@ -164,7 +164,7 @@ Player::action()
 
   base.x += base.xm * frame_ratio;
   base.y += base.ym * frame_ratio;
-
+  
   collision_swept_object_map(&old_base,&base);
 
   keep_in_bounds();
@@ -190,11 +190,9 @@ Player::action()
                 }
             }
           base.ym = physic_get_velocity(&vphysic);
-
         }
       else
         {
-
           /* Land: */
 
           if (base.ym > 0)
index e450ecd..454e082 100644 (file)
@@ -27,6 +27,7 @@ struct base_type
   float height;
 };
 
+
 struct string_list_type
 {
   int num_items;