- Physic C++ rewrite (Matze Braun)
authorTobias Gläßer <tobi.web@gmx.de>
Sun, 4 Apr 2004 00:32:10 +0000 (00:32 +0000)
committerTobias Gläßer <tobi.web@gmx.de>
Sun, 4 Apr 2004 00:32:10 +0000 (00:32 +0000)
- Added new badguys (Matze Braun)
- Fixed minor bugs (Matze Braun)

SVN-Revision: 430

17 files changed:
src/badguy.cpp
src/badguy.h
src/button.cpp
src/button.h
src/collision.cpp
src/collision.h
src/gameloop.cpp
src/leveleditor.cpp
src/physic.cpp
src/physic.h
src/player.cpp
src/player.h
src/scene.cpp
src/tile.cpp
src/tile.h
src/timer.cpp
src/title.cpp

index ce393bf..37d1968 100644 (file)
 #include "badguy.h"
 #include "scene.h"
 #include "screen.h"
-
-texture_type img_bsod_squished_left;
-texture_type img_bsod_squished_right;
-texture_type img_bsod_falling_left;
-texture_type img_bsod_falling_right;
-texture_type img_laptop_flat_left;
-texture_type img_laptop_flat_right;
-texture_type img_laptop_falling_left;
-texture_type img_laptop_falling_right;
+#include "tile.h"
+
+texture_type img_bsod_squished_left[1];
+texture_type img_bsod_squished_right[1];
+texture_type img_bsod_falling_left[1];
+texture_type img_bsod_falling_right[1];
+texture_type img_laptop_flat_left[1];
+texture_type img_laptop_flat_right[1];
+texture_type img_laptop_falling_left[1];
+texture_type img_laptop_falling_right[1];
 texture_type img_bsod_left[4];
 texture_type img_bsod_right[4];
 texture_type img_laptop_left[3];
@@ -33,12 +34,24 @@ 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_mrbomb_ticking_left;
-texture_type img_mrbomb_ticking_right;
-texture_type img_mrbomb_explosion;
-texture_type img_stalactite;
-texture_type img_stalactite_broken;
+texture_type img_mrbomb_ticking_left[1];
+texture_type img_mrbomb_ticking_right[1];
+texture_type img_mrbomb_explosion[1];
+texture_type img_stalactite[1];
+texture_type img_stalactite_broken[1];
 texture_type img_flame[2];
+texture_type img_fish[2];
+texture_type img_bouncingsnowball_left[6];
+texture_type img_bouncingsnowball_right[6];
+texture_type img_bouncingsnowball_squished[1];
+texture_type img_flyingsnowball[2];
+texture_type img_flyingsnowball_squished[1];
+texture_type img_spiky_left[3];
+texture_type img_spiky_right[3];
+texture_type img_snowball_left[3];
+texture_type img_snowball_right[3];
+texture_type img_snowball_squished_left[1];
+texture_type img_snowball_squished_right[1];
 
 BadGuyKind  badguykind_from_string(const std::string& str)
 {
@@ -54,9 +67,19 @@ BadGuyKind  badguykind_from_string(const std::string& str)
     return BAD_STALACTITE;
   else if (str == "flame")
     return BAD_FLAME;
+  else if (str == "fish")
+    return BAD_FISH;
+  else if (str == "bouncingsnowball")
+    return BAD_BOUNCINGSNOWBALL;
+  else if (str == "flyingsnowball")
+    return BAD_FLYINGSNOWBALL;
+  else if (str == "spiky")
+    return BAD_SPIKY;
+  else if (str == "snowball")
+    return BAD_SNOWBALL;
   else
     {
-      printf("Couldn't convert badguy: %s\n", str.c_str());
+      printf("Couldn't convert badguy: '%s'\n", str.c_str());
       return BAD_BSOD;
     }
 }
@@ -83,6 +106,21 @@ std::string badguykind_to_string(BadGuyKind kind)
     case BAD_FLAME:
       return "flame";
       break;
+    case BAD_FISH:
+      return "fish";
+      break;
+    case BAD_BOUNCINGSNOWBALL:
+      return "bouncingsnowball";
+      break;
+    case BAD_FLYINGSNOWBALL:
+      return "flyingsnowball";
+      break;
+    case BAD_SPIKY:
+      return "spiky";
+      break;
+    case BAD_SNOWBALL:
+      return "snowball";
+      break;
     default:
       return "bsod";
     }
@@ -93,51 +131,87 @@ BadGuy::init(float x, float y, BadGuyKind kind_)
 {
   base.x   = x;
   base.y   = y;    
-  base.width  = 32;
-  base.height = 32;
+  base.width  = 0;
+  base.height = 0;
+  base.xm  = 0;
+  base.ym  = 0;
+
   mode     = NORMAL;
   dying    = DYING_NOT;
   kind     = kind_;
-  base.xm  = -1.3;
-  base.ym  = 0;
   old_base = base;
   dir      = LEFT;
   seen     = false;
+  animation_speed = 1;
+  animation_length = 1;
+  animation_offset = 0;
+  texture_left = texture_right = 0;
+  physic.reset();
   timer_init(&timer, true);
-  physic_init(&physic);
 
-  if(kind == BAD_BOMB) {
-    timer_start(&timer, 1000);
-    mode = BOMB_TICKING;
+  if(kind == BAD_BSOD) {
+    physic.set_velocity(-1.3, 0);
+    set_texture(img_bsod_left, img_bsod_right, 4);
+  } else if(kind == BAD_MRBOMB) {
+    physic.set_velocity(-1.3, 0);
+    set_texture(img_mrbomb_left, img_mrbomb_right, 4);
+  } else if (kind == BAD_LAPTOP) {
+    physic.set_velocity(-1.3, 0);
+    set_texture(img_laptop_left, img_laptop_right, 3);
+  } else if(kind == BAD_MONEY) {
+    set_texture(img_money_left, img_money_right, 1);
+  } else if(kind == BAD_BOMB) {
+    set_texture(img_mrbomb_ticking_left, img_mrbomb_ticking_right, 1);
     // 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
-  } else if(kind == BAD_MONEY) {
-    base.ym = 4.8;
+    physic.enable_gravity(false);
+    set_texture(img_flame, img_flame, 2, 0.5);
+  } else if(kind == BAD_BOUNCINGSNOWBALL) {
+    physic.set_velocity(-1.3, 0);
+    set_texture(img_bouncingsnowball_left, img_bouncingsnowball_right, 6);
+  } else if(kind == BAD_STALACTITE) {
+    physic.enable_gravity(false);
+    set_texture(img_stalactite, img_stalactite, 1);
+  } else if(kind == BAD_FISH) {
+    set_texture(img_fish, img_fish, 2, 1);
+    physic.enable_gravity(true);
+  } else if(kind == BAD_FLYINGSNOWBALL) {
+    set_texture(img_flyingsnowball, img_flyingsnowball, 2);
+    physic.enable_gravity(false);
+  } else if(kind == BAD_SPIKY) {
+    physic.set_velocity(-1.3, 0);
+    set_texture(img_spiky_left, img_spiky_right, 3);
+  } else if(kind == BAD_SNOWBALL) {
+    physic.set_velocity(-1.3, 0);
+    set_texture(img_snowball_left, img_snowball_right, 3);
+  }
+
+  // if we're in a solid tile at start correct that now
+  if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(&base)) {
+    printf("Warning: badguy started in wall!.\n");
+    while(collision_object_map(&base))
+      --base.y;
   }
 }
 
-void BadGuy::action_bsod()
+void
+BadGuy::action_bsod()
 {
-  /* --- BLUE SCREEN OF DEATH MONSTER: --- */
-
-  /* Move left/right: */
-  if (dying == DYING_NOT || dying == DYING_FALLING)
-    {
-      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);
-               
-  if (!dying)
+  static const float BSODJUMP = 2;
+    
+  if (dying == DYING_NOT)
     check_horizontal_bump();
 
-  fall(true);
+  fall();
+
+  // jump when we're about to fall
+  if (physic.get_velocity_y() == 0 && 
+          !issolid(base.x+base.width/2, base.y + base.height)) {
+    physic.enable_gravity(true);
+    physic.set_velocity(physic.get_velocity_x(), BSODJUMP);
+  }
 
   // Handle dying timer:
   if (dying == DYING_SQUISHED && !timer_check(&timer))       
@@ -146,18 +220,25 @@ void BadGuy::action_bsod()
       remove_me();
       return;
     }
+
+  // move
+  physic.apply(base.x, base.y);
+  if(dying != DYING_FALLING)
+    collision_swept_object_map(&old_base, &base);
 }
 
-void BadGuy::action_laptop()
+void
+BadGuy::action_laptop()
 {
+  fall();
+  
   /* Move left/right: */
   if (mode == NORMAL || mode == KICK)
     {
-      if (dying == DYING_NOT ||
-          dying == DYING_FALLING)
-        {
-          base.x += base.xm * frame_ratio;
-        }
+      // move
+      physic.apply(base.x, base.y);
+      if (dying != DYING_FALLING)
+        collision_swept_object_map(&old_base,&base);
     }
   else if (mode == HELD)
     { /* FIXME: The pbad object shouldn't know about pplayer objects. */
@@ -187,21 +268,12 @@ void BadGuy::action_laptop()
             base.x += 24;
 
           mode=KICK;
-          base.xm = 8;
-          base.ym = 8;
+          set_texture(img_laptop_flat_left, img_laptop_flat_right, 1);
+          physic.set_velocity((dir == LEFT) ? -8 : 8, -8);
           play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER);
         }
     }
 
-
-  /* Move vertically: */
-  if(mode != HELD)
-    base.y = base.y + base.ym * frame_ratio;
-
-  if (dying != DYING_FALLING)
-    collision_swept_object_map(&old_base,&base);
-  /* Bump into things horizontally: */
-
   if (!dying)
     {
       int changed = dir;
@@ -218,101 +290,87 @@ void BadGuy::action_laptop()
         }
     }
 
-  fall();
-
   /* Handle mode timer: */
   if (mode == FLAT)
     {
       if(!timer_check(&timer))
         {
           mode = NORMAL;
-          base.xm = (dir == LEFT) ? -1.3 : 1.3;
+          set_texture(img_laptop_left, img_laptop_right, 3);
+          physic.set_velocity( (dir == LEFT) ? -1.3 : 1.3, 0);
         }
     }
 }
 
-void BadGuy::check_horizontal_bump(bool checkcliff)
+void
+BadGuy::check_horizontal_bump(bool checkcliff)
 {
-    if (dir == LEFT && issolid( base.x, (int) base.y + 16))
+    float halfheight = base.height / 2;
+    if (dir == LEFT && issolid( base.x, (int) base.y + halfheight))
     {
         dir = RIGHT;
-        base.xm = -base.xm;
+        physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
         return;
     }
-    if (dir == RIGHT && issolid( base.x + base.width, (int) base.y + 16))
+    if (dir == RIGHT && issolid( base.x + base.width, (int)base.y + halfheight))
     {
         dir = LEFT;
-        base.xm = -base.xm;
+        physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
         return;
     }
 
     // don't check for cliffs when we're falling
     if(!checkcliff)
         return;
-    if(!issolid(base.x + base.width/2, base.y + base.height + 16))
+    if(!issolid(base.x + base.width/2, base.y + base.height))
         return;
     
-    if(dir == LEFT && !issolid(base.x, (int) base.y + base.height + 16))
+    if(dir == LEFT && !issolid(base.x, (int) base.y + base.height + halfheight))
     {
-        printf("Cliffcol left\n");
         dir = RIGHT;
-        base.xm = -base.xm;
+        physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
         return;
     }
     if(dir == RIGHT && !issolid(base.x + base.width,
-                (int) base.y + base.height + 16))
+                (int) base.y + base.height + halfheight))
     {
-        printf("Cliffcol right\n");
         dir = LEFT;
-        base.xm = -base.xm;
+        physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
         return;
     }
 }
 
-void BadGuy::fall(bool dojump)
+void
+BadGuy::fall()
 {
   /* Fall if we get off the ground: */
   if (dying != DYING_FALLING)
     {
       if (!issolid(base.x+base.width/2, base.y + base.height))
         {
-          if(!physic_is_set(&physic))
-            {
-              physic_set_state(&physic,PH_VT);
-              physic_set_start_vy(&physic, dojump ? 2. : 0.);
-            }
-
-          base.ym = physic_get_velocity(&physic);
+          // not solid below us? enable gravity
+          physic.enable_gravity(true);
         }
       else
         {
           /* Land: */
-          if (base.ym > 0)
+          if (physic.get_velocity_y() < 0)
             {
               base.y = int((base.y + base.height)/32) * 32 - base.height;
-              base.ym = 0;
+              physic.set_velocity(physic.get_velocity_x(), 0);
             }
-          physic_init(&physic);
+          // no gravity anymore please
+          physic.enable_gravity(false);
         }
     }
   else
     {
-      if(!physic_is_set(&physic))
-        {                                                
-          physic_set_state(&physic,PH_VT);
-          physic_set_start_vy(&physic,0.);
-        }
-      base.ym = physic_get_velocity(&physic);
+      physic.enable_gravity(true);
     }
-
-  // BadGuy fall below the ground
-  if (base.y > screen->h) {
-    remove_me();
-    return;
-  }
 }
 
-void BadGuy::remove_me()
+void
+BadGuy::remove_me()
 {
   std::vector<BadGuy>::iterator i;
   for(i = bad_guys.begin(); i != bad_guys.end(); ++i) {
@@ -323,102 +381,91 @@ void BadGuy::remove_me()
   }
 }
 
-void BadGuy::action_money()
+void
+BadGuy::action_money()
 {
-  /* Move vertically: */
-  base.y = base.y + base.ym * frame_ratio;
-
-  if (dying != DYING_FALLING)
-    collision_swept_object_map(&old_base,&base);
-
-  if (base.y > screen->h) {
-    remove_me();
-    return;
-  }
-
-  if(physic_get_state(&physic) == -1)
+  static const float JUMPV = 6;
+    
+  fall();
+  // jump when on ground
+  if(dying == DYING_NOT && issolid(base.x, base.y+32))
     {
-      physic_set_state(&physic,PH_VT);
-      physic_set_start_vy(&physic,0.);
+      physic.set_velocity(physic.get_velocity_x(), JUMPV);
+      physic.enable_gravity(true);
+      set_texture(&img_money_left[1], &img_money_right[1], 1);
+      mode = MONEY_JUMP;
     }
-
-  if (dying != DYING_FALLING)
+  else if(mode == MONEY_JUMP)
     {
-      
-      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);
-          mode = MONEY_JUMP;
-        }
-      else
-        {
-          base.ym = physic_get_velocity(&physic);
-          mode = NORMAL;
-        }
+      set_texture(&img_money_left[0], &img_money_right[0], 1);
+      mode = NORMAL;
     }
+
+  // set direction based on tux
+  if(tux.base.x > base.x)
+    dir = RIGHT;
   else
-    {
-      if(!physic_is_set(&physic))
-        {
-          physic_set_state(&physic,PH_VT);
-          physic_set_start_vy(&physic,0.);
-        }
-      base.ym = physic_get_velocity(&physic);
-    } 
+    dir = LEFT;
+
+  // move
+  physic.apply(base.x, base.y);
+  if(dying == DYING_NOT)
+    collision_swept_object_map(&old_base, &base);
 }
 
-void BadGuy::action_mrbomb()
+void
+BadGuy::action_mrbomb()
 {
-  if(mode == NORMAL) {
-    base.x += base.xm * frame_ratio;
-  }
+  if (dying == DYING_NOT)
+    check_horizontal_bump(true);
 
-  /* Move vertically: */
-  base.y += base.ym * frame_ratio;
+  fall();
 
+  physic.apply(base.x, base.y);
   if (dying != DYING_FALLING)
-    collision_swept_object_map(&old_base,&base);
-
-  check_horizontal_bump(true);
-  fall();
+    collision_swept_object_map(&old_base,&base); 
 }
 
-void BadGuy::action_bomb()
+void
+BadGuy::action_bomb()
 {
-  // eventually fall down
-  base.y += base.ym * frame_ratio;
-  collision_swept_object_map(&old_base,&base);
+  static const int TICKINGTIME = 1000;
+  static const int EXPLODETIME = 1000;
+    
   fall();
 
-  if(!timer_check(&timer)) {
+  if(mode == NORMAL) {
+    mode = BOMB_TICKING;
+    timer_start(&timer, TICKINGTIME);
+  } else if(!timer_check(&timer)) {
     if(mode == BOMB_TICKING) {
       mode = BOMB_EXPLODE;
+      set_texture(img_mrbomb_explosion, img_mrbomb_explosion, 1);
       dying = DYING_NOT; // now the bomb hurts
-      timer_start(&timer, 1000);
-      // explosion image has different size
-      base.x -= (img_mrbomb_explosion.w - base.width) / 2;
-      base.y -= img_mrbomb_explosion.h - base.height;
-      base.width = img_mrbomb_explosion.w;
-      base.height = img_mrbomb_explosion.h;
-      old_base = base;
+      timer_start(&timer, EXPLODETIME);
     } else if(mode == BOMB_EXPLODE) {
       remove_me();
       return;
     }
   }
+
+  // move
+  physic.apply(base.x, base.y);                 
+  collision_swept_object_map(&old_base,&base);
 }
 
-void BadGuy::action_stalactite()
+void
+BadGuy::action_stalactite()
 {
+  static const int SHAKETIME = 800;
+  static const int RANGE = 40;
+    
   if(mode == NORMAL) {
-    static const int range = 40;
     // start shaking when tux is below the stalactite and at least 40 pixels
     // near
-    if(tux.base.x + 32 > base.x - range && tux.base.x < base.x + 32 + range
+    if(tux.base.x + 32 > base.x - RANGE && tux.base.x < base.x + 32 + RANGE
             && tux.base.y + tux.base.height > base.y) {
-      timer_start(&timer, 800);
+      timer_start(&timer, SHAKETIME);
       mode = STALACTITE_SHAKING;
     }
   } if(mode == STALACTITE_SHAKING) {
@@ -427,20 +474,24 @@ void BadGuy::action_stalactite()
       mode = STALACTITE_FALL;
     }
   } else if(mode == STALACTITE_FALL) {
-    base.y += base.ym * frame_ratio;
     fall();
-    /* Destroy if collides land */
-    if(issolid(base.x+16, base.y+32))
+    /* Destroy if we collides with land */
+    if(issolid(base.x+base.width/2, base.y+base.height))
     {
-      timer_start(&timer, 3000);
+      timer_start(&timer, 2000);
       dying = DYING_SQUISHED;
       mode = FLAT;
+      set_texture(img_stalactite_broken, img_stalactite_broken, 1);
     }
   } else if(mode == FLAT) {
-    if(!timer_check(&timer)) {
-      remove_me();
-    }
+    fall();
   }
+
+  // move
+  physic.apply(base.x, base.y);
+
+  if(dying == DYING_SQUISHED && !timer_check(&timer))
+    remove_me();
 }
 
 void
@@ -455,6 +506,145 @@ BadGuy::action_flame()
 }
 
 void
+BadGuy::action_fish()
+{
+  static const float JUMPV = 6;
+  static const int WAITTIME = 1000;
+    
+  // go in wait mode when back in water
+  if(dying == DYING_NOT && gettile(base.x, base.y+ base.height)->water
+        && physic.get_velocity_y() <= 0 && mode == NORMAL)
+    {
+      mode = FISH_WAIT;
+      set_texture(0, 0);
+      physic.set_velocity(0, 0);
+      physic.enable_gravity(false);
+      timer_start(&timer, WAITTIME);
+    }
+  else if(mode == FISH_WAIT && !timer_check(&timer))
+    {
+      // jump again
+      set_texture(img_fish, img_fish, 2, 1.5);
+      animation_offset = global_frame_counter; // restart animation
+      mode = NORMAL;
+      physic.set_velocity(0, JUMPV);
+      physic.enable_gravity(true);
+    }
+
+  physic.apply(base.x, base.y);
+  if(dying == DYING_NOT)
+    collision_swept_object_map(&old_base, &base);
+}
+
+void
+BadGuy::action_bouncingsnowball()
+{
+  static const float JUMPV = 4.5;
+    
+  fall();
+
+  // jump when on ground
+  if(dying == DYING_NOT && issolid(base.x, base.y+32))
+    {
+      physic.set_velocity(physic.get_velocity_x(), JUMPV);
+      physic.enable_gravity(true);
+    }                                                     
+  else
+    {
+      mode = NORMAL;
+    }
+
+  // check for right/left collisions
+  check_horizontal_bump();
+
+  physic.apply(base.x, base.y);
+  if(dying == DYING_NOT)
+    collision_swept_object_map(&old_base, &base);
+
+  // Handle dying timer:
+  if (dying == DYING_SQUISHED && !timer_check(&timer))       
+    {
+      /* Remove it if time's up: */
+      remove_me();
+      return;
+    }
+}
+
+void
+BadGuy::action_flyingsnowball()
+{
+  static const float FLYINGSPEED = 1;
+  static const int DIRCHANGETIME = 1000;
+    
+  // go into flyup mode if none specified yet
+  if(dying == DYING_NOT && mode == NORMAL) {
+    mode = FLY_UP;
+    physic.set_velocity(physic.get_velocity_x(), FLYINGSPEED);
+    timer_start(&timer, DIRCHANGETIME/2);
+  }
+
+  if(dying == DYING_NOT && !timer_check(&timer)) {
+    if(mode == FLY_UP) {
+      mode = FLY_DOWN;
+      physic.set_velocity(physic.get_velocity_x(), -FLYINGSPEED);
+    } else if(mode == FLY_DOWN) {
+      mode = FLY_UP;
+      physic.set_velocity(physic.get_velocity_x(), FLYINGSPEED);
+    }
+    timer_start(&timer, DIRCHANGETIME);
+  }
+
+  if(dying != DYING_NOT)
+    physic.enable_gravity(true);
+
+  physic.apply(base.x, base.y);
+  if(dying == DYING_NOT || dying == DYING_SQUISHED)
+    collision_swept_object_map(&old_base, &base);
+
+  // Handle dying timer:
+  if (dying == DYING_SQUISHED && !timer_check(&timer))       
+    {
+      /* Remove it if time's up: */
+      remove_me();
+      return;
+    }                                                          
+}
+
+void
+BadGuy::action_spiky()
+{
+  if (dying == DYING_NOT)
+    check_horizontal_bump();
+
+  fall();
+#if 0
+  // jump when we're about to fall
+  if (physic.get_velocity_y() == 0 && 
+          !issolid(base.x+base.width/2, base.y + base.height)) {
+    physic.enable_gravity(true);
+    physic.set_velocity(physic.get_velocity_x(), 2);
+  }
+#endif
+
+  physic.apply(base.x, base.y);
+  if (dying != DYING_FALLING)
+    collision_swept_object_map(&old_base,&base);   
+}
+
+void
+BadGuy::action_snowball()
+{
+  if (dying == DYING_NOT)
+    check_horizontal_bump();
+
+  fall();
+
+  physic.apply(base.x, base.y);
+  if (dying != DYING_FALLING)
+    collision_swept_object_map(&old_base,&base);
+}
+
+void
 BadGuy::action()
 {
   // Remove if it's far off the screen:
@@ -464,6 +654,12 @@ BadGuy::action()
       return;
     }
 
+  // BadGuy fall below the ground
+  if (base.y > screen->h) {
+    remove_me();
+    return;
+  }
+
   // Once it's on screen, it's activated!
   if (base.x <= scroll_x + screen->w + OFFSCREEN_DISTANCE)
     seen = true;
@@ -500,176 +696,104 @@ BadGuy::action()
     case BAD_FLAME:
       action_flame();
       break;
-    }
-}
 
-void
-BadGuy::draw_bsod()
-{
-  texture_type* texture = 0;
-  
-  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;
-  }
-  
-  texture_draw(texture, 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 = &img_laptop_right[frame];
-    } else {
-      texture = (dir == LEFT) ? &img_laptop_flat_left : &img_laptop_flat_right;
-    }
-  } else {
-    texture = (dir == LEFT) 
-        ? &img_laptop_falling_left : &img_laptop_falling_right;
-  }
+    case BAD_FISH:
+      action_fish();
+      break;
 
-  texture_draw(texture, base.x - scroll_x, base.y);
-}
+    case BAD_BOUNCINGSNOWBALL:
+      action_bouncingsnowball();
+      break;
 
-void
-BadGuy::draw_money()
-{
-  texture_type* texture;
-  size_t frame = (mode == NORMAL) ? 0 : 1;
+    case BAD_FLYINGSNOWBALL:
+      action_flyingsnowball();
+      break;
 
-  if(tux.base.x + tux.base.width < base.x) {
-    texture = &img_money_left[frame];
-  } else {
-    texture = &img_money_right[frame];
-  }
+    case BAD_SPIKY:
+      action_spiky();
+      break;
 
-  texture_draw(texture, base.x - scroll_x, base.y);
+    case BAD_SNOWBALL:
+      action_snowball();
+      break;
+    }
 }
-  
+
 void
-BadGuy::draw_mrbomb()
+BadGuy::draw()
 {
-  texture_type* texture;
-  size_t frame = (global_frame_counter/5) % 4;
-
-  if(dir == LEFT)
-    texture = &img_mrbomb_left[frame];
-  else
-    texture = &img_mrbomb_right[frame];
+  // 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;
+  if(texture_left == 0 || texture_right == 0)
+    return;
 
+  float global_frame = (float(global_frame_counter - animation_offset) / 10);
+  global_frame *= animation_speed;
+  size_t frame = size_t(global_frame) % animation_length;
+  texture_type* texture = 
+      (dir == LEFT) ? &texture_left[frame] : &texture_right[frame];
   texture_draw(texture, base.x - scroll_x, base.y);
 }
 
 void
-BadGuy::draw_bomb()
+BadGuy::set_texture(texture_type* left, texture_type* right,
+    int nanimlength, float nanimspeed)
 {
-  texture_type* texture;
-
-  // TODO add real bomb graphics
-  if(mode == BOMB_TICKING) {
-    texture = (dir == LEFT) 
-        ? &img_mrbomb_ticking_left : &img_mrbomb_ticking_right;
+  if(left != 0) {
+    if(base.width == 0 && base.height == 0) {
+      base.width = left->w;
+      base.height = left->h;
+    } else if(base.width != left->w || base.height != left->h) {
+      base.x -= (left->w - base.width) / 2;
+      base.y -= left->h - base.height;
+      base.width = left->w;
+      base.height = left->h;
+      old_base = base;
+    }
   } else {
-    texture = &img_mrbomb_explosion;
+    base.width = base.height = 0;
   }
-  
-  texture_draw(texture, base.x - scroll_x, base.y);
-}
 
-void
-BadGuy::draw_stalactite()
-{
-  texture_type* texture;
-  if(mode != FLAT)
-    texture = &img_stalactite;
-  else
-    texture = &img_stalactite_broken;
-
-  texture_draw(texture, base.x - scroll_x, base.y);
+  animation_length = nanimlength;
+  animation_speed = nanimspeed;
+  animation_offset = 0;
+  texture_left = left;
+  texture_right = right;
 }
 
 void
-BadGuy::draw_flame()
+BadGuy::bump()
 {
-  size_t frame = (global_frame_counter / 10) % 2;
-  texture_type* texture = &img_flame[frame];
-
-  texture_draw(texture, base.x - scroll_x, base.y);
+  if(kind == BAD_BSOD || kind == BAD_LAPTOP || kind == BAD_MRBOMB
+      || kind == BAD_BOUNCINGSNOWBALL) {
+    kill_me();
+  }
 }
 
 void
-BadGuy::draw()
+BadGuy::make_player_jump(Player* player)
 {
-  // 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;
-      
-  switch (kind)
-    {
-    case BAD_BSOD:
-      draw_bsod();
-      break;
-
-    case BAD_LAPTOP:
-      draw_laptop();
-      break;
-
-    case BAD_MONEY:
-      draw_money();
-      break;
-
-    case BAD_MRBOMB:
-      draw_mrbomb();
-      break;
-
-    case BAD_BOMB:
-      draw_bomb();
-      break;
-
-    case BAD_STALACTITE:
-      draw_stalactite();
-      break;
-
-    case BAD_FLAME:
-      draw_flame();
-      break;
-
-    }
+  player->physic.set_velocity(player->physic.get_velocity_x(), 2);
+  player->base.y = base.y - player->base.height - 2;
 }
 
 void
-BadGuy::bump()
+BadGuy::squish_me(Player* player)
 {
-  if(kind == BAD_BSOD || kind == BAD_LAPTOP || kind == BAD_BOMB) {
-    dying = DYING_FALLING;
-    base.ym = -8;
-    play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
-  }
-}
+  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++;
 
-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 - 2;
+  dying = DYING_SQUISHED;
+  timer_start(&timer, 2000);
+  physic.set_velocity(0, 0);
 }
 
 void
-BadGuy::squich(Player* player)
+BadGuy::squish(Player* player)
 {
   if(kind == BAD_MRBOMB) {
       // mrbomb transforms into a bomb now
@@ -684,18 +808,9 @@ BadGuy::squich(Player* player)
       return;
 
   } else if(kind == BAD_BSOD) {
-      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++;
-
-      dying = DYING_SQUISHED;
-      timer_start(&timer, 2000);
-      base.y += base.height - img_bsod_squished_left.h;
-      base.height = img_bsod_squished_left.h;
-      base.xm = base.ym = 0;
-      old_base = base;
+      squish_me(player);
+      set_texture(img_bsod_squished_left, img_bsod_squished_right, 1);
+      physic.set_velocity(0, physic.get_velocity_y());
       return;
       
   } else if (kind == BAD_LAPTOP) {
@@ -704,7 +819,8 @@ BadGuy::squich(Player* player)
           /* Flatten! */
           play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
           mode = FLAT;
-          base.xm = 0;
+          set_texture(img_laptop_flat_left, img_laptop_flat_right, 1);
+          physic.set_velocity(0, physic.get_velocity_y());
 
           timer_start(&timer, 4000);
       } else if (mode == FLAT) {
@@ -712,14 +828,15 @@ BadGuy::squich(Player* player)
           play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
 
           if (player->base.x < base.x + (base.width/2)) {
-              base.xm = 5;
+              physic.set_velocity(5, physic.get_velocity_y());
               dir = RIGHT;
           } else {
-              base.xm = -5;
+              physic.set_velocity(-5, physic.get_velocity_y());
               dir = LEFT;
           }
 
           mode = KICK;
+          set_texture(img_laptop_flat_left, img_laptop_flat_right, 1);
       }
 
       make_player_jump(player);
@@ -727,10 +844,58 @@ BadGuy::squich(Player* player)
       add_score(base.x - scroll_x, base.y, 25 * score_multiplier);
       score_multiplier++;
       return;
+  } else if(kind == BAD_FISH) {
+    make_player_jump(player);
+             
+    add_score(base.x - scroll_x, base.y, 25 * score_multiplier);
+    score_multiplier++;
+     
+    // simply remove the fish...
+    remove_me();
+    return;
+  } else if(kind == BAD_BOUNCINGSNOWBALL) {
+    squish_me(player);
+    set_texture(img_bouncingsnowball_squished,img_bouncingsnowball_squished,1);
+    return;
+  } else if(kind == BAD_FLYINGSNOWBALL) {
+    squish_me(player);
+    set_texture(img_flyingsnowball_squished,img_flyingsnowball_squished,1);
+    return;
+  } else if(kind == BAD_SNOWBALL) {
+    squish_me(player);
+    set_texture(img_snowball_squished_left, img_snowball_squished_right, 1);
+    return;
   }
 }
 
 void
+BadGuy::kill_me()
+{
+  if(kind == BAD_BOMB || kind == BAD_STALACTITE || kind == BAD_FLAME)
+    return;
+
+  dying = DYING_FALLING;
+  if(kind == BAD_LAPTOP)
+    set_texture(img_laptop_falling_left, img_laptop_falling_right, 1);
+  else if(kind == BAD_BSOD)
+    set_texture(img_bsod_falling_left, img_bsod_falling_right, 1);
+  
+  physic.enable_gravity(true);
+  physic.set_velocity(physic.get_velocity_x(), 0);
+
+  /* Gain some points: */
+  if (kind == BAD_BSOD)
+    add_score(base.x - scroll_x, base.y,
+              50 * score_multiplier);
+  else 
+    add_score(base.x - scroll_x, base.y,                                 
+              25 * score_multiplier);
+
+  /* Play death sound: */
+  play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
+}
+
+void
 BadGuy::collision(void *p_c_object, int c_object, CollisionType type)
 {
   BadGuy* pbad_c    = NULL;
@@ -739,55 +904,27 @@ BadGuy::collision(void *p_c_object, int c_object, CollisionType type)
     bump();
     return;
   }
-  if(type == COLLISION_SQUICH) {
+  if(type == COLLISION_SQUISH) {
     Player* player = static_cast<Player*>(p_c_object);
-    squich(player);
+    squish(player);
     return;
   }
 
   switch (c_object)
     {
     case CO_BULLET:
-      if(kind == BAD_BOMB || kind == BAD_STALACTITE || kind == BAD_FLAME)
-        return;
-
-      dying = DYING_FALLING;
-      base.ym = -8;
-
-      /* Gain some points: */
-      if (kind == BAD_BSOD)
-        add_score(base.x - scroll_x, base.y,
-                  50 * score_multiplier);
-      else if (kind == BAD_LAPTOP)
-        add_score(base.x - scroll_x, base.y,
-                  25 * score_multiplier);
-      else if (kind == BAD_MONEY)
-        add_score(base.x - scroll_x, base.y,
-                  50 * score_multiplier);
-
-      /* Play death sound: */
-      play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
+      kill_me();
       break;
 
     case CO_BADGUY:
       pbad_c = (BadGuy*) p_c_object;
-      if(kind == BAD_LAPTOP && mode == KICK)
+      if(kind == BAD_LAPTOP && mode == KICK &&
+            pbad_c->kind != BAD_FLAME && pbad_c->kind != BAD_BOMB)
         {
           /* We're in kick mode, kill the other guy
             and yourself(wuahaha) : */
-
-          pbad_c->dying = DYING_FALLING;
-          pbad_c->base.ym = -8;
-          play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
-
-          add_score(base.x - scroll_x,
-                    base.y, 100);
-                 
-          dying = DYING_FALLING;
-          base.ym = -8;
-
-          add_score(pbad_c->base.x - scroll_x,
-                    pbad_c->base.y, 100);
+          pbad_c->kill_me();
+          kill_me();
         }
       break;
     }
@@ -830,19 +967,19 @@ void load_badguy_gfx()
                "/images/shared/bsod-right-3.png",
                USE_ALPHA);
 
-  texture_load(&img_bsod_squished_left, datadir +
+  texture_load(&img_bsod_squished_left[0], datadir +
                "/images/shared/bsod-squished-left.png",
                USE_ALPHA);
 
-  texture_load(&img_bsod_squished_right, datadir +
+  texture_load(&img_bsod_squished_right[0], datadir +
                "/images/shared/bsod-squished-right.png",
                USE_ALPHA);
 
-  texture_load(&img_bsod_falling_left, datadir +
+  texture_load(&img_bsod_falling_left[0], datadir +
                "/images/shared/bsod-falling-left.png",
                USE_ALPHA);
 
-  texture_load(&img_bsod_falling_right, datadir +
+  texture_load(&img_bsod_falling_right[0], datadir +
                "/images/shared/bsod-falling-right.png",
                USE_ALPHA);
 
@@ -873,19 +1010,19 @@ void load_badguy_gfx()
                "/images/shared/laptop-right-2.png",
                USE_ALPHA);
 
-  texture_load(&img_laptop_flat_left, datadir +
+  texture_load(&img_laptop_flat_left[0], datadir +
                "/images/shared/laptop-flat-left.png",
                USE_ALPHA);
 
-  texture_load(&img_laptop_flat_right, datadir +
+  texture_load(&img_laptop_flat_right[0], datadir +
                "/images/shared/laptop-flat-right.png",
                USE_ALPHA);
 
-  texture_load(&img_laptop_falling_left, datadir +
+  texture_load(&img_laptop_falling_left[0], datadir +
                "/images/shared/laptop-falling-left.png",
                USE_ALPHA);
 
-  texture_load(&img_laptop_falling_right, datadir +
+  texture_load(&img_laptop_falling_right[0], datadir +
                "/images/shared/laptop-falling-right.png",
                USE_ALPHA);
 
@@ -917,17 +1054,17 @@ void load_badguy_gfx()
       texture_load(&img_mrbomb_right[i],
               datadir + "/images/shared/mrbomb-right-" + num + ".png", USE_ALPHA);
   }
-  texture_load(&img_mrbomb_ticking_left,
+  texture_load(&img_mrbomb_ticking_left[0],
           datadir + "/images/shared/mrbombx-left-0.png", USE_ALPHA);
-  texture_load(&img_mrbomb_ticking_right,
+  texture_load(&img_mrbomb_ticking_right[0],
           datadir + "/images/shared/mrbombx-right-0.png", USE_ALPHA);
-  texture_load(&img_mrbomb_explosion,
+  texture_load(&img_mrbomb_explosion[0],
           datadir + "/images/shared/mrbomb-explosion.png", USE_ALPHA);
 
   /* stalactite */
-  texture_load(&img_stalactite, 
+  texture_load(&img_stalactite[0]
           datadir + "/images/shared/stalactite.png", USE_ALPHA);
-  texture_load(&img_stalactite_broken,
+  texture_load(&img_stalactite_broken[0],
           datadir + "/images/shared/stalactite-broken.png", USE_ALPHA);
 
   /* flame */
@@ -935,6 +1072,62 @@ void load_badguy_gfx()
           datadir + "/images/shared/flame-0.png", USE_ALPHA);
   texture_load(&img_flame[1],
           datadir + "/images/shared/flame-1.png", USE_ALPHA);  
+
+  /* fish */
+  texture_load(&img_fish[0],
+          datadir + "/images/shared/fish-left-0.png", USE_ALPHA);
+  texture_load(&img_fish[1],
+          datadir + "/images/shared/fish-left-1.png", USE_ALPHA);
+
+  /* bouncing snowball */
+  for(int i=0; i<6; ++i) {
+      char num[4];
+      snprintf(num, 4, "%d", i);
+      texture_load(&img_bouncingsnowball_left[i],
+              datadir + "/images/shared/bouncingsnowball-left-" + num + ".png",
+              USE_ALPHA);
+      texture_load(&img_bouncingsnowball_right[i],
+              datadir + "/images/shared/bouncingsnowball-right-" + num + ".png",
+              USE_ALPHA);
+  } 
+  texture_load(&img_bouncingsnowball_squished[0],
+          datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA);
+
+  /* flying snowball */
+  texture_load(&img_flyingsnowball[0],
+          datadir + "/images/shared/flyingsnowball-left-0.png", USE_ALPHA);
+  texture_load(&img_flyingsnowball[1],
+          datadir + "/images/shared/flyingsnowball-left-1.png", USE_ALPHA);  
+  texture_load(&img_flyingsnowball_squished[0],
+          datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA);
+
+  /* spiky */
+  for(int i = 0; i < 3; ++i) {
+        char num[4];
+        snprintf(num, 4, "%d", i);
+        texture_load(&img_spiky_left[i],                                 
+                datadir + "/images/shared/spiky-left-" + num + ".png",   
+                USE_ALPHA);
+        texture_load(&img_spiky_right[i],
+                datadir + "/images/shared/spiky-right-" + num + ".png",
+                USE_ALPHA);
+  }
+
+  /** snowball */
+  for(int i = 0; i < 3; ++i) {
+        char num[4];
+        snprintf(num, 4, "%d", i);
+        texture_load(&img_snowball_left[i],
+                datadir + "/images/shared/snowball-left-" + num + ".png",
+                USE_ALPHA);
+        texture_load(&img_snowball_right[i],
+                datadir + "/images/shared/snowball-right-" + num + ".png",
+                USE_ALPHA);
+  }
+  texture_load(&img_snowball_squished_left[0],
+          datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA);
+  texture_load(&img_snowball_squished_right[0],
+          datadir + "/images/shared/bsod-squished-right.png", USE_ALPHA);  
 }
 
 void free_badguy_gfx()
@@ -945,11 +1138,11 @@ void free_badguy_gfx()
       texture_free(&img_bsod_right[i]);
     }
 
-  texture_free(&img_bsod_squished_left);
-  texture_free(&img_bsod_squished_right);
+  texture_free(&img_bsod_squished_left[0]);
+  texture_free(&img_bsod_squished_right[0]);
 
-  texture_free(&img_bsod_falling_left);
-  texture_free(&img_bsod_falling_right);
+  texture_free(&img_bsod_falling_left[0]);
+  texture_free(&img_bsod_falling_right[0]);
 
   for (int i = 0; i < 3; i++)
     {
@@ -957,11 +1150,11 @@ void free_badguy_gfx()
       texture_free(&img_laptop_right[i]);
     }
 
-  texture_free(&img_laptop_flat_left);
-  texture_free(&img_laptop_flat_right);
+  texture_free(&img_laptop_flat_left[0]);
+  texture_free(&img_laptop_flat_right[0]);
 
-  texture_free(&img_laptop_falling_left);
-  texture_free(&img_laptop_falling_right);
+  texture_free(&img_laptop_falling_left[0]);
+  texture_free(&img_laptop_falling_right[0]);
 
   for (int i = 0; i < 2; i++)
     {
@@ -974,15 +1167,39 @@ void free_badguy_gfx()
       texture_free(&img_mrbomb_right[i]);
   }
 
-  texture_free(&img_mrbomb_ticking_left);
-  texture_free(&img_mrbomb_ticking_right);
-  texture_free(&img_mrbomb_explosion);
+  texture_free(&img_mrbomb_ticking_left[0]);
+  texture_free(&img_mrbomb_ticking_right[0]);
+  texture_free(&img_mrbomb_explosion[0]);
 
-  texture_free(&img_stalactite);
-  texture_free(&img_stalactite_broken);
+  texture_free(&img_stalactite[0]);
+  texture_free(&img_stalactite_broken[0]);
 
   texture_free(&img_flame[0]);
   texture_free(&img_flame[1]);
+
+  texture_free(&img_fish[0]);
+  texture_free(&img_fish[1]);
+
+  for(int i=0; i<6; ++i) {
+    texture_free(&img_bouncingsnowball_left[i]);
+    texture_free(&img_bouncingsnowball_right[i]);
+  }
+  texture_free(&img_bouncingsnowball_squished[0]);
+
+  texture_free(&img_flyingsnowball[0]);
+  texture_free(&img_flyingsnowball[1]);
+  texture_free(&img_flyingsnowball_squished[0]);
+
+  for(int i = 0; i<3; ++i) {
+    texture_free(&img_spiky_left[i]);
+    texture_free(&img_spiky_right[i]);
+  }
+  for(int i = 0; i<3; ++i) {
+    texture_free(&img_snowball_left[i]);
+    texture_free(&img_snowball_right[i]);
+  }
+  texture_free(&img_snowball_squished_left[0]);
+  texture_free(&img_snowball_squished_right[0]); 
 }
 
 // EOF //
index 71cf4d1..5c7ed10 100644 (file)
@@ -39,7 +39,12 @@ enum {
     BOMB_EXPLODE,
 
     STALACTITE_SHAKING,
-    STALACTITE_FALL
+    STALACTITE_FALL,
+
+    FISH_WAIT,
+
+    FLY_UP,
+    FLY_DOWN
 };
 
 /* Bad guy kinds: */
@@ -50,7 +55,12 @@ enum BadGuyKind {
   BAD_MRBOMB,
   BAD_BOMB,
   BAD_STALACTITE,
-  BAD_FLAME
+  BAD_FLAME,
+  BAD_FISH,
+  BAD_BOUNCINGSNOWBALL,
+  BAD_FLYINGSNOWBALL,
+  BAD_SPIKY,
+  BAD_SNOWBALL
 };
 
 BadGuyKind  badguykind_from_string(const std::string& str);
@@ -76,18 +86,26 @@ class Player;
 /* Badguy type: */
 class BadGuy
 {
- public:
-  int mode;
+public:
   DyingType dying;
+  base_type base;
   BadGuyKind kind;
-  bool seen;
+  int mode;
   int dir;
-  base_type base;
+
+private:
+  bool seen;
   base_type old_base;
   timer_type timer;
-  physic_type physic;
+  Physic physic;
 
- public:
+  texture_type* texture_left;
+  texture_type* texture_right;
+  int animation_offset;
+  size_t animation_length;
+  float animation_speed;
+
+public:
   void init(float x, float y, BadGuyKind kind);
 
   void action();
@@ -95,36 +113,49 @@ class BadGuy
 
   void collision(void* p_c_object, int c_object,
           CollisionType type = COLLISION_NORMAL);
-  
- private:
-  void fall(bool dojump=false);
-  void remove_me();
 
+  /** this functions tries to kill the badguy and lets him fall off the
+   * screen. Some badguys like the flame might ignore this.
+   */
+  void kill_me();
+  
+private:
   void action_bsod();
-  void draw_bsod();
-
   void action_laptop();
-  void draw_laptop();
-   
   void action_money(); 
-  void draw_money();
-
   void action_bomb();
-  void draw_bomb();
-
   void action_mrbomb();
-  void draw_mrbomb();
-
   void action_stalactite();
-  void draw_stalactite();
-
   void action_flame();
-  void draw_flame();
-
+  void action_fish();
+  void action_bouncingsnowball();
+  void action_flyingsnowball();
+  void action_spiky();
+  void action_snowball();
+
+  /** 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
+   */
   void check_horizontal_bump(bool checkcliff = false);
+  /** called when we're bumped from below with a block */
   void bump();
-  void squich(Player* player);
+  /** called when a player jumped on the badguy from above */
+  void squish(Player* player);
+  /** squish ourself, give player score and set dying to DYING_SQICHED */
+  void squish_me(Player* player);
+  /** set image of the badguy */
+  void set_texture(texture_type* left, texture_type* right,
+        int animlength = 1, float animspeed = 1);
 };
 
 #endif /*SUPERTUX_BADGUY_H*/
index f6541d9..54f889e 100644 (file)
 #include "globals.h"
 #include "button.h"
 
+timer_type Button::popup_timer;
+
 Button::Button(std::string icon_file, std::string ninfo, SDLKey nshortcut, int x, int y, int mw, int mh)
 {
+  timer_init(&popup_timer,false);
+
   char filename[1024];
 
   if(!icon_file.empty())
@@ -85,6 +89,10 @@ void Button::change_icon(std::string icon_file, int mw, int mh)
 
 void Button::draw()
 {
+  if(state == BUTTON_HOVER)
+    if(!timer_check(&popup_timer))
+     show_info = true;
+
   fillrect(rect.x,rect.y,rect.w,rect.h,75,75,75,200);
   fillrect(rect.x+1,rect.y+1,rect.w-2,rect.h-2,175,175,175,200);
   if(bkgd != NULL)
@@ -152,7 +160,7 @@ void Button::event(SDL_Event &event)
           mouse_cursor->set_state(MC_LINK);
         }
     }
-  else if(event.type != SDL_KEYDOWN && event.type != SDL_KEYUP)
+  else if((event.type != SDL_KEYDOWN && event.type != SDL_KEYUP) || event.type == SDL_MOUSEMOTION)
     {
       state = BUTTON_NONE;
       if(show_info)
@@ -173,12 +181,14 @@ void Button::event(SDL_Event &event)
     }
   else if(event.type == SDL_MOUSEMOTION)
     {
-
+      timer_start(&popup_timer, 1500);
+    
       if(show_info)
         {
           show_info = false;
         }
     }
+    
 }
 
 int Button::get_state()
@@ -214,7 +224,7 @@ Button* ButtonPanel::event(SDL_Event& event)
       for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
         {
           (*it)->event(event);
-          if((*it)->state != -1)
+          if((*it)->state != BUTTON_NONE)
             return (*it);
         }
       return NULL;
@@ -236,6 +246,7 @@ ButtonPanel::~ButtonPanel()
 
 void ButtonPanel::draw()
 {
+
   if(hidden == false)
     {
       fillrect(rect.x,rect.y,rect.w,rect.h,100,100,100,200);
index d80e823..53dc828 100644 (file)
@@ -42,6 +42,7 @@ class Button
     }
 
   private:
+    static timer_type popup_timer;
     texture_type icon;
     texture_type* bkgd;
     std::string info;
index 5820db1..c875903 100644 (file)
@@ -244,6 +244,8 @@ void collision_handler()
         }
     }
 
+  if(tux.dying != DYING_NOT) return;
+    
   // CO_BADGUY & CO_PLAYER check 
   for(unsigned int i = 0; i < bad_guys.size(); ++i)
     {
@@ -257,7 +259,7 @@ void collision_handler()
           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].collision(&tux, CO_PLAYER, COLLISION_SQUICH);
+              bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_SQUISH);
             }
           else
             {
index 410e2e8..3f048d3 100644 (file)
@@ -25,7 +25,7 @@ enum
 enum CollisionType {
     COLLISION_NORMAL,
     COLLISION_BUMP,
-    COLLISION_SQUICH
+    COLLISION_SQUISH
 };
 
 bool rectcollision(base_type* one, base_type* two);
index 3dac681..6718c13 100644 (file)
@@ -469,9 +469,7 @@ void game_draw(void)
   int y,x;
 
   /* Draw screen: */
-  if (tux.dying && (global_frame_counter % 4) == 0)
-    clearscreen(255, 255, 255);
-  else if(timer_check(&super_bkgd_timer))
+  if(timer_check(&super_bkgd_timer))
     texture_draw(&img_super_bkgd, 0, 0);
   else
     {
@@ -611,6 +609,7 @@ int gameloop(const char * subset, int levelnb, int mode)
     }
 
   level_load_gfx(&current_level);
+  loadshared();
   activate_bad_guys(&current_level);
   activate_particle_systems();
   level_load_song(&current_level);
@@ -620,8 +619,6 @@ int gameloop(const char * subset, int levelnb, int mode)
   if(st_gl_mode != ST_GL_TEST)
     load_hs();
 
-  loadshared();
-
   if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
     levelintro();
 
@@ -640,6 +637,7 @@ int gameloop(const char * subset, int levelnb, int mode)
   game_pause = 0;
   timer_init(&fps_timer,true);
   timer_init(&frame_timer,true);
+  last_update_time = st_get_ticks();
   fps_cnt = 0;
 
   /* Clear screen: */
@@ -1177,65 +1175,6 @@ void drawshape(float x, float y, unsigned int c, Uint8 alpha)
             }
         }
     }
-
-  /*
-  if (c == 'X' || c == 'x')
-    texture_draw(&img_brick[0], x, y);
-  else if (c == 'Y' || c == 'y')
-    texture_draw(&img_brick[1], x, y);
-  else if (c == 'A' || c =='B' || c == '!')
-    texture_draw(&img_box_full, x, y);
-  else if (c == 'a')
-    texture_draw(&img_box_empty, x, y);
-  else if (c >= 'C' && c <= 'F')
-    texture_draw(&img_cloud[0][c - 'C'], x, y);
-  else if (c >= 'c' && c <= 'f')
-    texture_draw(&img_cloud[1][c - 'c'], x, y);
-  else if (c >= 'G' && c <= 'J')
-    texture_draw(&img_bkgd_tile[0][c - 'G'], x, y);
-  else if (c >= 'g' && c <= 'j')
-    texture_draw(&img_bkgd_tile[1][c - 'g'], x, y);
-  else if (c == '#')
-    texture_draw(&img_solid[0], x, y);
-  else if (c == '[')
-    texture_draw(&img_solid[1], x, y);
-  else if (c == '=')
-    texture_draw(&img_solid[2], x, y);
-  else if (c == ']')
-    texture_draw(&img_solid[3], x, y);
-  else if (c == '$')
-    {
-      z = (global_frame_counter / 2) % 6;
-
-      if (z < 4)
-        texture_draw(&img_distro[z], x, y);
-      else if (z == 4)
-        texture_draw(&img_distro[2], x, y);
-      else if (z == 5)
-        texture_draw(&img_distro[1], x, y);
-    }
-  else if (c == '^')
-    {
-      z = (global_frame_counter / 3) % 3;
-
-      texture_draw(&img_waves[z], x, y);
-    }
-  else if (c == '*')
-    texture_draw(&img_poletop, x, y);
-  else if (c == '|')
-    {
-      texture_draw(&img_pole, x, y);
-
-    }
-  else if (c == '\\')
-    {
-      z = (global_frame_counter / 3) % 2;
-
-      texture_draw(&img_flag[z], x + 16, y);
-    }
-  else if (c == '&')
-    texture_draw(&img_water, x, y);*/
-
 }
 
 
@@ -1657,8 +1596,6 @@ void loadgame(int slot)
       timer_fread(&tux.frame_timer,fi);
       timer_fread(&time_left,fi);
       fread(&ui,sizeof(int),1,fi);
-      tux.hphysic.start_time += st_get_ticks() - ui;
-      tux.vphysic.start_time += st_get_ticks() - ui;
       fclose(fi);
     }
 
index b0598be..25cf9be 100644 (file)
@@ -861,20 +861,6 @@ void le_checkevents()
                 }
               else if(event.button.button == SDL_BUTTON_RIGHT)
                {
-               switch(active_tm)
-               {
-               case TM_BG:
-                  active_tm = TM_IA;
-                  break;
-               case TM_IA:
-                  active_tm = TM_FG;
-                  break;
-               case TM_FG:
-                  active_tm = TM_BG;
-                  break;
-               default:
-                  break;
-               }
                 le_mouse_pressed[RIGHT] = true;
                }
               break;
@@ -1066,7 +1052,7 @@ void le_checkevents()
         }
       else if(le_move_left_bt->get_state() == BUTTON_HOVER)
         {
-          pos_x -= 96;
+          pos_x -= 64;
         }
 
       if(le_move_right_bt->get_state() == BUTTON_PRESSED)
@@ -1075,7 +1061,7 @@ void le_checkevents()
         }
       else if(le_move_right_bt->get_state() == BUTTON_HOVER)
         {
-          pos_x += 96;
+          pos_x += 64;
         }
     }
 
@@ -1247,7 +1233,7 @@ void le_showhelp()
   text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
 
   for(i = 0; i < sizeof(text)/sizeof(char *); i++)
-    text_draw(&white_small_text, text[i], 5, 80+(i*12), 1);
+    text_draw(&white_text, text[i], 5, 80+(i*18), 1);
 
   text_drawf(&gold_text, "Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
 
@@ -1257,16 +1243,7 @@ void le_showhelp()
 
   while(done == 0)
     {
-      while(SDL_PollEvent(&event))
-        switch(event.type)
-          {
-          case SDL_MOUSEBUTTONDOWN:            // mouse pressed
-          case SDL_KEYDOWN:            // key pressed
-            done = 1;
-            break;
-          default:
-            break;
-          }
+      done = wait_for_event(event);
       SDL_Delay(50);
     }
 }
index 3b2813a..f315661 100644 (file)
@@ -9,75 +9,86 @@
 // Copyright: See COPYING file that comes with this distribution
 //
 //
-
 #include <stdio.h>
+
+#include "scene.h"
 #include "defines.h"
 #include "physic.h"
+#include "timer.h"
 
 float gravity;
 
-void physic_init(physic_type* pphysic)
+Physic::Physic()
+    : ax(0), ay(0), vx(0), vy(0), gravity_enabled(true)
 {
-  pphysic->state = -1;
-  pphysic->start_time = 0;
-  pphysic->start_vy = 0;
 }
 
-int physic_get_state(physic_type* pphysic)
+Physic::~Physic()
 {
-  return pphysic->state;
 }
 
-void physic_set_state(physic_type* pphysic, int nstate)
+void
+Physic::reset()
 {
-  pphysic->state = nstate;
-  pphysic->start_time = st_get_ticks();
+    ax = ay = vx = vy = 0;
+    gravity_enabled = true;
 }
 
-void physic_set_start_vy(physic_type* pphysic, float start_vy)
+void
+Physic::set_velocity(float nvx, float nvy)
 {
-  pphysic->start_vy = start_vy;
+    vx = nvx;
+    vy = -nvy;
 }
 
-void physic_set_start_vx(physic_type* pphysic, float start_vx)
+float
+Physic::get_velocity_x()
 {
-  pphysic->start_vx = start_vx;
+    return vx;
 }
 
-void physic_set_acceleration(physic_type* pphysic, float acceleration)
+float
+Physic::get_velocity_y()
 {
-  pphysic->acceleration = acceleration;
+    return -vy;
 }
 
-
-int physic_is_set(physic_type* pphysic)
+void
+Physic::set_acceleration(float nax, float nay)
 {
-  return (pphysic->state != -1);
+    ax = nax;
+    ay = -nay;
 }
 
-float physic_get_velocity(physic_type* pphysic)
+float
+Physic::get_acceleration_x()
 {
-  if(pphysic->state == PH_VT)
-    return - (pphysic->start_vy - gravity* ((float)(st_get_ticks() - pphysic->start_time))/1000.);
-  else if(pphysic->state == PH_HA)
-    return - (pphysic->start_vx - pphysic->acceleration * ((float)(st_get_ticks() - pphysic->start_time))/1000.);
-  else
-    return 0;
+    return ax;
 }
 
-float physic_get_max_distance(physic_type* pphysic)
+float
+Physic::get_acceleration_y()
 {
-  return (pphysic->start_vy * pphysic->start_vy / 2.*gravity);
+    return -ay;
 }
 
-unsigned int physic_get_max_time(physic_type* pphysic)
+void
+Physic::enable_gravity(bool enable_gravity)
 {
-  return (unsigned int)((pphysic->start_vy / gravity) * 1000);
+    gravity_enabled = enable_gravity;
 }
 
-unsigned int physic_get_time_gone(physic_type* pphysic)
+void
+Physic::apply(float &x, float &y)
 {
-  return st_get_ticks() - pphysic->start_time;
+    float grav;
+    if(gravity_enabled)
+        grav = gravity / 100.0;
+    else
+        grav = 0;
+
+    x += vx * frame_ratio + ax * frame_ratio * frame_ratio;
+    y += vy * frame_ratio + (ay + grav) * frame_ratio * frame_ratio;
+    vx += ax * frame_ratio;
+    vy += (ay + grav) * frame_ratio;
 }
-
-
index f980bcb..8608021 100644 (file)
 #ifndef SUPERTUX_PHYSIC_H
 #define SUPERTUX_PHYSIC_H
 
-#include "timer.h"
-
-enum {
-  PH_VT, /* Vertical throw.*/
-  PH_HA  /* Horizontal acceleration. */
-};
-
-/* Physic type: */
-
-struct physic_type
-  {
-    int state;
-    float start_vy;
-    float start_vx;
-    float acceleration;
-    unsigned int start_time;
+/** This is a very simplistic physics engine handling accelerated and constant
+  * movement along with gravity.
+  */
+class Physic
+{
+public:
+    Physic();
+    ~Physic();
+
+    /** resets all velocities and accelerations to 0 */
+    void reset();
+
+    /** sets velocity to a fixed value */
+    void set_velocity(float vx, float vy);
+
+    float get_velocity_x();
+    float get_velocity_y();
+    
+    /** sets acceleration applied to the object. (Note that gravity is
+     * eventually added to the vertical acceleration)
+     */
+    void set_acceleration(float ax, float ay);
+
+    float get_acceleration_x();
+    float get_acceleration_y();
+
+    /** enables or disables handling of gravity */
+    void enable_gravity(bool gravity_enabled);
+
+    /** applies the physical simulation to given x and y coordinates */
+    void apply(float &x, float &y); 
+
+private:
+    /// horizontal and vertical acceleration
+    float ax, ay;
+    /// horizontal and vertical velocity
+    float vx, vy;
+    /// should we respect gravity in out calculations?
+    bool gravity_enabled;
 };
 
 /* global variables. */
 extern float gravity;
 
-void physic_init(physic_type* pphysic);
-int physic_get_state(physic_type* pphysic);
-void physic_set_state(physic_type* pphysic, int nstate);
-void physic_set_start_vy(physic_type* pphysic, float start_vy);
-void physic_set_start_vx(physic_type* pphysic, float start_vx);
-void physic_set_acceleration(physic_type* pphysic, float acceleration);
-int physic_is_set(physic_type* pphysic);
-float physic_get_velocity(physic_type* pphysic);
-float physic_get_max_distance(physic_type* pphysic);
-unsigned int physic_get_max_time(physic_type* pphysic);
-unsigned int physic_get_time_gone(physic_type* pphysic);
-
 #endif /*SUPERTUX_PHYSIC_H*/
index 9b40c01..f23dc6b 100644 (file)
@@ -9,6 +9,7 @@
 // Copyright: See COPYING file that comes with this distribution
 //
 //
+#include <math.h>
 
 #include "gameloop.h"
 #include "globals.h"
@@ -66,7 +67,6 @@ Player::init()
   // FIXME: Make the start position configurable via the levelfile
   base.x = 100;
   base.y = 240;
-
   base.xm = 0;
   base.ym = 0;
   old_base = base;
@@ -94,8 +94,7 @@ Player::init()
   timer_init(&skidding_timer,true);
   timer_init(&safe_timer,true);
   timer_init(&frame_timer,true);
-  physic_init(&hphysic);
-  physic_init(&vphysic);
+  physic.reset();
 }
 
 int
@@ -138,6 +137,9 @@ Player::level_begin()
   base.xm = 0;
   base.ym = 0;
   old_base = base;
+  previous_base = base;
+
+  dying = DYING_NOT;
 
   player_input_init(&input);
 
@@ -145,8 +147,7 @@ Player::level_begin()
   timer_init(&skidding_timer,true);
   timer_init(&safe_timer,true);
   timer_init(&frame_timer,true);
-  physic_init(&hphysic);
-  physic_init(&vphysic);
+  physic.reset();
 }
 
 void
@@ -160,12 +161,9 @@ Player::action()
     handle_input();
 
   /* Move tux: */
-
   previous_base = base;
 
-  base.x += base.xm * frame_ratio;
-  base.y += base.ym * frame_ratio;
-
+  physic.apply(base.x, base.y);
 
   if (!dying)
     {
@@ -178,36 +176,25 @@ Player::action()
 
       if( !on_ground())
         {
+          physic.enable_gravity(true);
           if(under_solid())
             {
-              physic_set_state(&vphysic,PH_VT);
-              physic_set_start_vy(&vphysic,0);
+              // fall down
+              physic.set_velocity(physic.get_velocity_x(), 0);
               jumped_in_solid = true;
             }
-          else
-            {
-              if(!physic_is_set(&vphysic))
-                {
-                  physic_set_state(&vphysic,PH_VT);
-                  physic_set_start_vy(&vphysic,0);
-                }
-            }
-          base.ym = physic_get_velocity(&vphysic);
         }
       else
         {
           /* Land: */
-
-          if (base.ym > 0)
+          if (physic.get_velocity_y() < 0)
             {
               base.y = (int)(((int)base.y / 32) * 32);
-              base.ym = 0;
+              physic.set_velocity(physic.get_velocity_x(), 0);
             }
 
-          physic_init(&vphysic);
-
+          physic.enable_gravity(false);
           /* Reset score multiplier (for multi-hits): */
-
           score_multiplier = 1;
         }
 
@@ -253,8 +240,6 @@ Player::action()
         }
 
     }
-  else
-    base.ym = physic_get_velocity(&vphysic);
 
   timer_check(&safe_timer);
 
@@ -292,7 +277,7 @@ Player::action()
 
   /* Handle skidding: */
 
-  timer_check(&skidding_timer);
+  // timer_check(&skidding_timer); // disabled
 
   /* End of level? */
 
@@ -322,80 +307,105 @@ Player::under_solid()
 void
 Player::handle_horizontal_input(int newdir)
 {
-  if ((newdir ? (base.xm < -SKID_XM) : (base.xm > SKID_XM)) && !timer_started(&skidding_timer) &&
-      dir == !newdir && on_ground())
+  if(duck)
+    return;
+
+  float vx = physic.get_velocity_x();
+  float vy = physic.get_velocity_y();
+  dir = newdir;
+
+  // skid if we're too fast
+  if(dir != newdir && on_ground() && fabs(physic.get_velocity_x()) > SKID_XM 
+          && !timer_started(&skidding_timer))
     {
       timer_start(&skidding_timer, SKID_TIME);
-
       play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
-
+      return;
     }
-  dir = newdir;
-
 
-  if ((newdir ? (base.xm < 0) : (base.xm > 0)) && !isice(base.x, base.y + base.height) &&
+  if ((newdir ? (vx < 0) : (vx > 0)) && !isice(base.x, base.y + base.height) &&
       !timer_started(&skidding_timer))
     {
-      base.xm = 0;
+      //vx = 0;
     }
 
-  if (!duck)
+  /* Facing the direction we're jumping?  Go full-speed: */
+  if (input.fire == UP)
     {
-      if (dir == newdir)
+      if(vx >= MAX_WALK_XM) {
+        vx = MAX_WALK_XM;
+        physic.set_acceleration(0, 0); // enough speedup
+      } else if(vx <= -MAX_WALK_XM) {
+        vx = -MAX_WALK_XM;
+        physic.set_acceleration(0, 0);
+      }
+      physic.set_acceleration(newdir ? 0.02 : -0.02, 0);
+      if(fabs(vx) < 1) // set some basic run speed
+        vx = newdir ? 1 : -1;
+#if 0
+      vx += ( newdir ? WALK_SPEED : -WALK_SPEED) * frame_ratio;
+
+      if(newdir)
         {
-          /* Facing the direction we're jumping?  Go full-speed: */
-
-          if (input.fire == UP)
-            {
-              base.xm = base.xm + ( newdir ? WALK_SPEED : -WALK_SPEED) * frame_ratio;
-
-              if(newdir)
-                {
-                  if (base.xm > MAX_WALK_XM)
-                    base.xm = MAX_WALK_XM;
-                }
-              else
-                {
-                  if (base.xm < -MAX_WALK_XM)
-                    base.xm = -MAX_WALK_XM;
-                }
-            }
-          else if ( input.fire == DOWN)
-            {
-              base.xm = base.xm + ( newdir ? RUN_SPEED : -RUN_SPEED) * frame_ratio;
-
-              if(newdir)
-                {
-                  if (base.xm > MAX_RUN_XM)
-                    base.xm = MAX_RUN_XM;
-                }
-              else
-                {
-                  if (base.xm < -MAX_RUN_XM)
-                    base.xm = -MAX_RUN_XM;
-                }
-            }
-          else
-            {
-              /* Not facing the direction we're jumping?
-                 Go half-speed: */
-
-              base.xm = base.xm + ( newdir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio;
-
-              if(newdir)
-                {
-                  if (base.xm > MAX_WALK_XM / 2)
-                    base.xm = MAX_WALK_XM / 2;
-                }
-              else
-                {
-                  if (base.xm < -MAX_WALK_XM / 2)
-                    base.xm = -MAX_WALK_XM / 2;
-                }
-            }
+          if (vx > MAX_WALK_XM)
+            vx = MAX_WALK_XM;
+        }
+      else
+        {
+          if (vx < -MAX_WALK_XM)
+            vx = -MAX_WALK_XM;
+        }
+#endif
+    }
+  else if ( input.fire == DOWN)
+    {
+      if(vx >= MAX_RUN_XM) {
+        vx = MAX_RUN_XM;
+        physic.set_acceleration(0, 0); // enough speedup      
+      } else if(vx <= -MAX_RUN_XM) {
+        vx = -MAX_RUN_XM;
+        physic.set_acceleration(0, 0);
+      }
+      physic.set_acceleration(newdir ? 0.03 : -0.03, 0);
+      if(fabs(vx) < 1) // set some basic run speed
+        vx = newdir ? 1 : -1;
+
+#if 0
+      vx = vx + ( newdir ? RUN_SPEED : -RUN_SPEED) * frame_ratio;
+
+      if(newdir)
+        {
+          if (vx > MAX_RUN_XM)
+            vx = MAX_RUN_XM;
+        }
+      else
+        {
+          if (vx < -MAX_RUN_XM)
+            vx = -MAX_RUN_XM;
         }
+#endif
+    }
+  else
+    {
+#if 0
+      /* Not facing the direction we're jumping?
+         Go half-speed: */
+      vx = vx + ( newdir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio;
 
+      if(newdir)
+        {
+          if (vx > MAX_WALK_XM / 2)
+            vx = MAX_WALK_XM / 2;
+        }
+      else
+        {
+          if (vx < -MAX_WALK_XM / 2)
+            vx = -MAX_WALK_XM / 2;
+        }
+#endif
     }
+  
+  physic.set_velocity(vx, vy);
 }
 
 void
@@ -405,45 +415,22 @@ Player::handle_vertical_input()
     {
       if (on_ground())
         {
-          if(!physic_is_set(&vphysic))
-            {
-              physic_set_state(&vphysic,PH_VT);
-              physic_set_start_vy(&vphysic,5.5);
-              --base.y;
-              jumping = true;
-              if (size == SMALL)
-                play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
-              else
-                play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
-            }
+          // jump
+          physic.set_velocity(physic.get_velocity_x(), 5.5);
+          --base.y;
+          jumping = true;
+          if (size == SMALL)
+            play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
+          else
+            play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
         }
     }
   else if(input.up == UP && jumping)
     {
-      if (on_ground())
-        {
-          physic_init(&vphysic);
-          jumping = false;
-        }
-      else
-        {
-          jumping = false;
-          if(physic_is_set(&vphysic))
-            {
-              if(physic_get_velocity(&vphysic) < 0.)
-                {
-                  physic_set_state(&vphysic,PH_VT);
-                  physic_set_start_vy(&vphysic,0);
-                }
-            }
-          else
-            {
-              if(!physic_is_set(&vphysic))
-                {
-                  physic_set_state(&vphysic,PH_VT);
-                }
-            }
-        }
+      jumping = false;
+      if(physic.get_velocity_y() > 0) {
+        physic.set_velocity(physic.get_velocity_x(), 0);
+      }
     }
 }
 
@@ -463,18 +450,15 @@ Player::handle_input()
         }
       else
         {
-          if(base.xm > 0)
-            {
-              base.xm = (int)(base.xm - frame_ratio);
-              if(base.xm < 0)
-                base.xm = 0;
-            }
-          else if(base.xm < 0)
-            {
-              base.xm = (int)(base.xm + frame_ratio);
-              if(base.xm > 0)
-                base.xm = 0;
-            }
+          float vx = physic.get_velocity_x();
+          if(fabs(vx) < 0.01) {
+            physic.set_velocity(0, physic.get_velocity_y());
+            physic.set_acceleration(0, 0);
+          } else if(vx < 0) {
+            physic.set_acceleration(0.1, 0);
+          } else {
+            physic.set_acceleration(-0.1, 0);
+          }
         }
     }
 
@@ -489,7 +473,7 @@ Player::handle_input()
 
   if (input.fire == DOWN && input.old_fire == UP && got_coffee)
     {
-      add_bullet(base.x, base.y, base.xm, dir);
+      add_bullet(base.x, base.y, physic.get_velocity_x(), dir);
     }
 
 
@@ -659,7 +643,7 @@ Player::draw()
                 {
                   if (!timer_started(&skidding_timer))
                     {
-                      if (!jumping || base.ym > 0)
+                      if (!jumping || physic.get_velocity_y() > 0)
                         {
                           if (dir == RIGHT)
                             {
@@ -720,7 +704,7 @@ Player::draw()
                 {
                   if (!timer_started(&skidding_timer))
                     {
-                      if (!jumping || base.ym > 0)
+                      if (!jumping || physic.get_velocity_y() > 0)
                         {
                           if (dir == RIGHT)
                             {
@@ -775,6 +759,7 @@ Player::draw()
             }
         }
     }
+
   if(dying)
     text_drawf(&gold_text,"Penguins can fly !:",0,0,A_HMIDDLE,A_VMIDDLE,1);
 }
@@ -794,60 +779,34 @@ Player::collision(void* p_c_object, int c_object)
           !timer_started(&safe_timer) &&
           pbad_c->mode != HELD)
         {
-          if (pbad_c->mode == FLAT  && input.fire != DOWN)
-            {
-              /* Kick: */
-
-              pbad_c->mode = KICK;
-              play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
-
-              if (base.x < pbad_c->base.x + (pbad_c->base.width/2))
-                {
-                  pbad_c->dir = RIGHT;
-                  pbad_c->base.x = pbad_c->base.x + 16;
-                }
-              else
-                {
-                  pbad_c->dir = LEFT;
-                  pbad_c->base.x = pbad_c->base.x - 32;
-                }
-
-              timer_start(&pbad_c->timer,5000);
-            }
-          else if (pbad_c->mode == FLAT && input.fire == DOWN)
+          if (pbad_c->mode == FLAT && input.fire == DOWN)
             {
               pbad_c->mode = HELD;
               pbad_c->base.y-=8;
             }
           else if (pbad_c->mode == KICK)
             {
-              if (base.y < pbad_c->base.y - 16 &&
-                  timer_started(&pbad_c->timer))
+              if (base.y < pbad_c->base.y - 16)
                 {
                   /* Step on (stop being kicked) */
 
                   pbad_c->mode = FLAT;
                   play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
-                  timer_start(&pbad_c->timer, 10000);
                 }
               else
                 {
                   /* Hurt if you get hit by kicked laptop: */
-
-                  if (timer_started(&pbad_c->timer))
+                  if (!timer_started(&invincible_timer))
                     {
-                      if (!timer_started(&invincible_timer))
-                        {
-                          kill(SHRINK);
-                        }
-                      else
-                        {
-                          pbad_c->dying = DYING_FALLING;
-                          play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
-                          add_score(pbad_c->base.x - scroll_x,
-                                    pbad_c->base.y,
-                                    25 * score_multiplier);
-                        }
+                      kill(SHRINK);
+                    }
+                  else
+                    {
+                      pbad_c->dying = DYING_FALLING;
+                      play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
+                      add_score(pbad_c->base.x - scroll_x,
+                                pbad_c->base.y,
+                                25 * score_multiplier);
                     }
                 }
             }
@@ -859,11 +818,7 @@ Player::collision(void* p_c_object, int c_object)
                 }
               else
                 {
-                  pbad_c->dying = DYING_FALLING;
-                  play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
-                  add_score(pbad_c->base.x - scroll_x,
-                            pbad_c->base.y,
-                            25 * score_multiplier);
+                  pbad_c->kill_me();
                 }
             }
           score_multiplier++;
@@ -880,10 +835,9 @@ Player::collision(void* p_c_object, int c_object)
 void
 Player::kill(int mode)
 {
-
   play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
 
-  base.xm = 0;
+  physic.set_velocity(0, physic.get_velocity_y());
 
   if (mode == SHRINK && size == BIG)
     {
@@ -899,8 +853,10 @@ Player::kill(int mode)
     {
       if(size == BIG)
         duck = true;
-      physic_set_state(&vphysic,PH_VT);
-      physic_set_start_vy(&vphysic,7);
+
+      physic.enable_gravity(true);
+      physic.set_acceleration(0, 0);
+      physic.set_velocity(0, 7);
       dying = DYING_SQUISHED;
     }
 }
@@ -908,8 +864,6 @@ Player::kill(int mode)
 void
 Player::is_dying()
 {
-  base.ym = base.ym + gravity;
-
   /* He died :^( */
 
   --lives;
index f222579..7f481b9 100644 (file)
@@ -107,8 +107,7 @@ class Player
   timer_type skidding_timer;
   timer_type safe_timer;
   timer_type frame_timer;
-  physic_type vphysic;
-  physic_type hphysic;
+  Physic physic;
 
  public:
   void init();
index 3fab869..c39fcfa 100644 (file)
@@ -121,9 +121,10 @@ void add_bouncy_brick(float x, float y)
 
 void add_bad_guy(float x, float y, BadGuyKind kind)
 {
-  BadGuy new_bad_guy;
+  bad_guys.push_back(BadGuy());
+  BadGuy& new_bad_guy = bad_guys.back();
+  
   new_bad_guy.init(x,y,kind);
-  bad_guys.push_back(new_bad_guy);
 }
 
 void add_upgrade(float x, float y, int dir, int kind)
index efe9777..3ced8ef 100644 (file)
@@ -46,6 +46,7 @@ void TileManager::load_tileset(std::string filename)
               tile->solid   = false;
               tile->brick   = false;
               tile->ice     = false;
+              tile->water   = false;
               tile->fullbox = false;
               tile->distro  = false;
               tile->data    = 0;
@@ -57,6 +58,7 @@ void TileManager::load_tileset(std::string filename)
               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_int("data",       &tile->data);
index 721b010..2175b2b 100644 (file)
@@ -40,6 +40,9 @@ struct Tile
   /** FIXME: ? */
   bool ice;
 
+  /** water */
+  bool water;
+
   /** Bonusbox, content is stored in \a data */
   bool fullbox;
 
index 858f3fe..52b1b08 100644 (file)
@@ -19,7 +19,7 @@ unsigned int st_pause_ticks, st_pause_count;
 unsigned int st_get_ticks(void)
 {
   if(st_pause_count != 0)
-    return SDL_GetTicks() - st_pause_ticks - SDL_GetTicks() + st_pause_count;
+    return /*SDL_GetTicks()*/ - st_pause_ticks /*- SDL_GetTicks()*/ + st_pause_count;
   else
     return SDL_GetTicks() - st_pause_ticks;
 }
@@ -37,6 +37,9 @@ void st_pause_ticks_start(void)
 
 void st_pause_ticks_stop(void)
 {
+if(st_pause_count == 0)
+return;
+
   st_pause_ticks += SDL_GetTicks() - st_pause_count;
   st_pause_count = 0;
 }
index a6f24fd..5b55235 100644 (file)
@@ -84,13 +84,12 @@ int title(void)
   Player titletux;
   titletux.init();
   st_pause_ticks_init();
-  st_pause_ticks_stop();
 
   level_load(&current_level, (datadir + "/levels/misc/menu.stl").c_str());
   loadshared();
   activate_particle_systems();
   /* Lower the gravity that tux doesn't jump to hectically through the demo */
-  gravity = 5;
+  //gravity = 5;
 
   /* Reset menu variables */
   menu_reset();
@@ -301,6 +300,10 @@ int title(void)
                         }
                     }
                 }
+              // reset tux
+              scroll_x = 0;
+              titletux.level_begin();
+              update_time = st_get_ticks();
               break;
             case 3:
               update_load_save_game_menu(load_game_menu, true);