Corrected collition with bag of money
[supertux.git] / src / player.c
index d56d147..759bb82 100644 (file)
@@ -4,7 +4,7 @@
 // Description:
 //
 //
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
+// Author: Tobias Glaesser <tobi.web@gmx.de> & Bill Kendrick, (C) 2004
 //
 // Copyright: See COPYING file that comes with this distribution
 //
 #include "scene.h"
 #include "screen.h"
 
+texture_type tux_life,
+tux_right[3],  tux_left[3],
+bigtux_right[3],  bigtux_left[3],
+bigtux_right_jump,  bigtux_left_jump,
+ducktux_right,  ducktux_left,
+skidtux_right,  skidtux_left,
+firetux_right[3],  firetux_left[3],
+bigfiretux_right[3],  bigfiretux_left[3],
+bigfiretux_right_jump,  bigfiretux_left_jump,
+duckfiretux_right,  duckfiretux_left,
+skidfiretux_right,  skidfiretux_left,
+cape_right[2],  cape_left[2],
+bigcape_right[2],  bigcape_left[2];
+
 void player_init(player_type* pplayer)
 {
   pplayer->base.width = 32;
   pplayer->base.height = 32;
 
-  pplayer->base.updated = SDL_GetTicks();
   pplayer->size = SMALL;
   pplayer->got_coffee = NO;
 
@@ -34,10 +47,7 @@ void player_init(player_type* pplayer)
   pplayer->duck = NO;
 
   pplayer->dying = NO;
-  pplayer->safe = TUX_SAFE_TIME;
-
   pplayer->jumping = NO;
-  pplayer->skidding = 0;
 
   pplayer->frame_main = 0;
   pplayer->frame = 0;
@@ -50,7 +60,46 @@ void player_init(player_type* pplayer)
   pplayer->input.right = UP;
   pplayer->input.up = UP;
 
+  pplayer->keymap.jump = SDLK_UP;
+  pplayer->keymap.duck = SDLK_DOWN;
+  pplayer->keymap.left = SDLK_LEFT;
+  pplayer->keymap.right = SDLK_RIGHT;
+  pplayer->keymap.fire = SDLK_LCTRL;
+
   timer_init(&pplayer->invincible_timer);
+  timer_init(&pplayer->skidding_timer);
+  timer_init(&pplayer->safe_timer);
+}
+
+int player_key_event(player_type* pplayer, SDLKey key, int state)
+{
+  if(key == pplayer->keymap.right)
+    {
+      pplayer->input.right = state;
+      return YES;
+    }
+  else if( key == pplayer->keymap.left)
+    {
+      pplayer->input.left = state;
+      return YES;
+    }
+  else if(key == pplayer->keymap.jump)
+    {
+      pplayer->input.up = state;
+      return YES;
+    }
+  else if(key == pplayer->keymap.duck)
+    {
+      pplayer->input.down = state;
+      return YES;
+    }
+  else if(key == pplayer->keymap.fire)
+    {
+      pplayer->input.fire = state;
+      return YES;
+    }
+  else
+    return NO;
 }
 
 void player_level_begin(player_type* pplayer)
@@ -59,13 +108,21 @@ void player_level_begin(player_type* pplayer)
   pplayer->base.y = 240;
   pplayer->base.xm = 0;
   pplayer->base.ym = 0;
+
+  pplayer->input.down = UP;
+  pplayer->input.fire = UP;
+  pplayer->input.left = UP;
+  pplayer->input.old_fire = UP;
+  pplayer->input.right = UP;
+  pplayer->input.up = UP;
+
+  timer_init(&pplayer->invincible_timer);
+  timer_init(&pplayer->skidding_timer);
+  timer_init(&pplayer->safe_timer);
 }
 
 void player_action(player_type* pplayer)
 {
-
-  double frame_ratio = get_frame_ratio(&pplayer->base);
-
   /* --- HANDLE TUX! --- */
 
   player_input(pplayer);
@@ -81,377 +138,484 @@ void player_action(player_type* pplayer)
 
   if (!pplayer->dying)
     {
-      if (issolid(pplayer->base.x, pplayer->base.y + 31) &&
-          !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y + 31))
+      /* FIXME: this code is COMPLETLY broken!!! */
+       /* if (issolid(pplayer->base.x, pplayer->base.y + 31) &&
+            !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y + 31))
+          {
+            while (issolid(pplayer->base.x, pplayer->base.y + 31))
+              {
+                if (pplayer->base.xm < 0)
+                  pplayer->base.x++;
+                else if (pplayer->base.xm > 0)
+                  pplayer->base.x--;
+              }
+
+            pplayer->base.xm = 0;
+          }*/
+
+        /*if (issolid(pplayer->base.x, pplayer->base.y) &&
+            !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y))
+          {
+            while (issolid(pplayer->base.x, (pplayer->base.y)))
+              {
+                if (pplayer->base.xm < 0)
+                  pplayer->base.x++;
+                else if (pplayer->base.xm > 0)
+                  pplayer->base.x--;
+              }
+
+            pplayer->base.xm = 0;
+          }*/
+
+        if (issolid(pplayer->base.x, pplayer->base.y + 31))
+          {
+            /* Set down properly: */
+
+            int debug_int = 0;
+            while (issolid(pplayer->base.x, pplayer->base.y + 31))
+              {
+                ++debug_int;
+                if(debug_int > 32)
+                  {
+                    DEBUG_MSG("FIXME - UNDER certain circumstances I'm hanging in a loop here!");
+                    /*the circumstances are:
+                    issolid() is true and base.ym == 0
+                    use of floating point varibles for base stuff*/
+                    break;
+                  }
+                if (pplayer->base.ym < 0)
+                  pplayer->base.y++;
+                else if (pplayer->base.ym > 0)
+                  pplayer->base.y--;
+              }
+
+
+            /* Reset score multiplier (for multi-hits): */
+
+            if (pplayer->base.ym > 0)
+              score_multiplier = 1;
+
+
+            /* Stop jumping! */
+
+      pplayer->base.ym = 0;
+      pplayer->jumping = NO;
+      pplayer->input.up = UP;
+      }
+            /* FIXME: this code is COMPLETLY broken!!! */
+      /*if (issolid(pplayer->base.x, pplayer->base.y) ||
+          (pplayer->size == BIG && !pplayer->duck &&
+           (issolid(pplayer->base.x, pplayer->base.y - 32))))
+        {*/
+      /*if (!issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y) &&
+          (pplayer->size == SMALL || pplayer->duck ||
+           !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32)))*/
+
+      if (((!issolid(pplayer->base.x, pplayer->base.y- pplayer->base.ym * frame_ratio) && (issolid(pplayer->base.x, pplayer->base.y) || issolid(pplayer->base.x, pplayer->base.y+31))))
+      ||((!issolid(pplayer->base.x - pplayer->base.xm * frame_ratio, pplayer->base.y) && (issolid(pplayer->base.x, pplayer->base.y) || issolid(pplayer->base.x+32, pplayer->base.y)))))
+          /*(pplayer->size == SMALL || pplayer->duck ||
+           !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32))*/
         {
-          while (issolid(pplayer->base.x, pplayer->base.y + 31))
+          pplayer->base.y = pplayer->base.y- pplayer->base.ym * frame_ratio;
+          pplayer->base.ym = 0;
+        }
+          
+      if (((issolid(pplayer->base.x, pplayer->base.y) || issolid(pplayer->base.x+32, pplayer->base.y)) &&  (!issolid(pplayer->base.x - pplayer->base.xm * frame_ratio, pplayer->base.y))
+          /*(pplayer->size == SMALL || pplayer->duck ||
+           !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32))*/) || 
+          (!issolid(pplayer->base.x - pplayer->base.xm * frame_ratio, pplayer->base.y+pplayer->base.height) && (issolid(pplayer->base.x, pplayer->base.y+pplayer->base.height) || issolid(pplayer->base.x +32, pplayer->base.y+pplayer->base.height))))
+        {
+         pplayer->base.x = pplayer->base.x- pplayer->base.xm * frame_ratio;
+          pplayer->base.xm = 0;
+        }
+       
+          if (pplayer->base.ym <= 0)
             {
-              if (pplayer->base.xm < 0)
-                pplayer->base.x++;
-              else if (pplayer->base.xm > 0)
-                pplayer->base.x--;
-            }
+      if (isbrick(pplayer->base.x, pplayer->base.y) ||
+          isfullbox(pplayer->base.x, pplayer->base.y))
+        {
+          trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
+          trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
+          bumpbrick(pplayer->base.x, pplayer->base.y);
+          tryemptybox(pplayer->base.x, pplayer->base.y);
+        }
 
-          pplayer->base.xm = 0;
+      if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
+          isfullbox(pplayer->base.x+ 31, pplayer->base.y))
+        {
+          trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
+          trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
+          bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
+          tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
         }
+      /* Get a distro from a brick? */
 
-      if (issolid(pplayer->base.x, pplayer->base.y) &&
-          !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y))
+      if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
+          shape(pplayer->base.x, pplayer->base.y) == 'y')
         {
-          while (issolid(pplayer->base.x, (pplayer->base.y)))
+          add_bouncy_distro(((pplayer->base.x+ 1)
+                             / 32) * 32,
+                            (int)(pplayer->base.y / 32) * 32);
+
+          if (counting_distros == NO)
             {
-              if (pplayer->base.xm < 0)
-                pplayer->base.x++;
-              else if (pplayer->base.xm > 0)
-                pplayer->base.x--;
+              counting_distros = YES;
+              distro_counter = 100;
             }
 
-          pplayer->base.xm = 0;
-        }
+          if (distro_counter <= 0)
+            level_change(&current_level,pplayer->base.x,pplayer->base.y, 'a');
 
-      if (issolid(pplayer->base.x, pplayer->base.y + 31))
+          play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
+          score = score + SCORE_DISTRO;
+          distros++;
+        }
+      else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
+               shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
         {
-          /* Set down properly: */
+          add_bouncy_distro(((pplayer->base.x+ 1 + 31)
+                             / 32) * 32,
+                            (int)(pplayer->base.y / 32) * 32);
 
-          int debug_int = 0;
-          while (issolid(pplayer->base.x, pplayer->base.y + 31))
+          if (counting_distros == NO)
             {
-              ++debug_int;
-              if(debug_int > 32)
-                DEBUG_MSG("FIXME - UNDER certain circumstances I'm hanging in a loop here!");
-               
-              if (pplayer->base.ym < 0)
-                pplayer->base.y++;
-              else if (pplayer->base.ym > 0)
-                pplayer->base.y--;
+              counting_distros = YES;
+              distro_counter = 100;
             }
 
+          if (distro_counter <= 0)
+            level_change(&current_level,pplayer->base.x+ 31, pplayer->base.y, 'a');
 
-          /* Reset score multiplier (for multi-hits): */
-
-          if (pplayer->base.ym > 0)
-            score_multiplier = 1;
+          play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
+          score = score + SCORE_DISTRO;
+          distros++;
+        }
+       
+       }
+       else
+{
+  pplayer->base.ym = 0;
+  pplayer->jumping = NO;
+  timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
+}
+  /*}*/
+  /* Bump into things: * /
+   
+  if (issolid(pplayer->base.x, pplayer->base.y) ||
+      (pplayer->size == BIG && !pplayer->duck &&
+       (issolid(pplayer->base.x, pplayer->base.y - 32))))
+    {
+   
+      if (!issolid(pplayer->base.x, pplayer->base.y - pplayer->base.ym) &&
+          (pplayer->size == SMALL || pplayer->duck ||
+           !issolid(pplayer->base.x, pplayer->base.y - 32 - pplayer->base.ym)))
+        {
+          if (pplayer->base.ym <= 0)
+            {
+              /* Jumping up? */
+      /* FIXME: this code is COMPLETLY broken!!! */
+  if (pplayer->size == BIG)
+    {
+      /* Break bricks and empty boxes: * /
 
+      if (!pplayer->duck)
+        {
+          if (isbrick(pplayer->base.x, pplayer->base.y - 32) ||
+              isfullbox(pplayer->base.x, pplayer->base.y - 32))
+            {
+              trygrabdistro(pplayer->base.x, pplayer->base.y - 64, BOUNCE);
+              trybumpbadguy(pplayer->base.x, pplayer->base.y - 96);
 
-          /* Stop jumping! */
+              if (isfullbox(pplayer->base.x, pplayer->base.y - 32))
+                {
+                  bumpbrick(pplayer->base.x, pplayer->base.y - 32);
+                }
 
-          pplayer->base.ym = 0;
-          pplayer->jumping = NO;
-        }
+              trybreakbrick(pplayer->base.x, pplayer->base.y - 32);
+              tryemptybox(pplayer->base.x, pplayer->base.y - 32);
+            }
 
+          if (isbrick(pplayer->base.x+ 31, pplayer->base.y - 32) ||
+              isfullbox(pplayer->base.x+ 31, pplayer->base.y - 32))
+            {
+              trygrabdistro(pplayer->base.x+ 31,
+                            pplayer->base.y - 64,
+                            BOUNCE);
+              trybumpbadguy(pplayer->base.x+ 31,
+                            pplayer->base.y - 96);
 
-      /* Bump into things: */
+              if (isfullbox(pplayer->base.x+ 31, pplayer->base.y - 32))
+                {
+                  bumpbrick(pplayer->base.x+ 31, pplayer->base.y - 32);
+                }
 
-      if (issolid(pplayer->base.x, pplayer->base.y) ||
-          (pplayer->size == BIG && !pplayer->duck &&
-           (issolid(pplayer->base.x, pplayer->base.y - 32))))
+              trybreakbrick(pplayer->base.x+ 31,
+                            pplayer->base.y - 32);
+              tryemptybox(pplayer->base.x+ 31,
+                          pplayer->base.y - 32);
+            }
+        }
+      else /* ducking * /
         {
-          if (!issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y) &&
-              (pplayer->size == SMALL || pplayer->duck ||
-               !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32)))
+          if (isbrick(pplayer->base.x, pplayer->base.y) ||
+              isfullbox(pplayer->base.x, pplayer->base.y))
             {
-              pplayer->base.x = pplayer->base.x- pplayer->base.xm;
-              pplayer->base.xm = 0;
+              trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
+              trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
+              if (isfullbox(pplayer->base.x, pplayer->base.y))
+                bumpbrick(pplayer->base.x, pplayer->base.y);
+              trybreakbrick(pplayer->base.x, pplayer->base.y);
+              tryemptybox(pplayer->base.x, pplayer->base.y);
             }
-          else if (!issolid(pplayer->base.x, pplayer->base.y - pplayer->base.ym) &&
-                   (pplayer->size == SMALL || pplayer->duck ||
-                    !issolid(pplayer->base.x, pplayer->base.y - 32 - pplayer->base.ym)))
+
+          if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
+              isfullbox(pplayer->base.x+ 31, pplayer->base.y))
             {
-              if (pplayer->base.ym <= 0)
-                {
-                  /* Jumping up? */
+              trygrabdistro(pplayer->base.x+ 31,
+                            pplayer->base.y - 32,
+                            BOUNCE);
+              trybumpbadguy(pplayer->base.x+ 31,
+                            pplayer->base.y - 64);
+              if (isfullbox(pplayer->base.x+ 31, pplayer->base.y))
+                bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
+              trybreakbrick(pplayer->base.x+ 31, pplayer->base.y);
+              tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
+            }
+        }
+      }
+      else
+      {
+      /* It's a brick and we're small, make the brick
+         bounce, and grab any distros above it: * /
 
-                  if (pplayer->size == BIG)
-                    {
-                      /* Break bricks and empty boxes: */
+      if (isbrick(pplayer->base.x, pplayer->base.y) ||
+          isfullbox(pplayer->base.x, pplayer->base.y))
+        {
+          trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
+          trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
+          bumpbrick(pplayer->base.x, pplayer->base.y);
+          tryemptybox(pplayer->base.x, pplayer->base.y);
+        }
 
-                      if (!pplayer->duck)
-                        {
-                          if (isbrick(pplayer->base.x, pplayer->base.y - 32) ||
-                              isfullbox(pplayer->base.x, pplayer->base.y - 32))
-                            {
-                              trygrabdistro(pplayer->base.x, pplayer->base.y - 64, BOUNCE);
-                              trybumpbadguy(pplayer->base.x, pplayer->base.y - 96);
+      if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
+          isfullbox(pplayer->base.x+ 31, pplayer->base.y))
+        {
+          trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
+          trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
+          bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
+          tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
+        }
 
-                              if (isfullbox(pplayer->base.x, pplayer->base.y - 32))
-                                {
-                                  bumpbrick(pplayer->base.x, pplayer->base.y - 32);
-                                }
 
-                              trybreakbrick(pplayer->base.x, pplayer->base.y - 32);
-                              tryemptybox(pplayer->base.x, pplayer->base.y - 32);
-                            }
+      /* Get a distro from a brick? * /
 
-                          if (isbrick(pplayer->base.x+ 31, pplayer->base.y - 32) ||
-                              isfullbox(pplayer->base.x+ 31, pplayer->base.y - 32))
-                            {
-                              trygrabdistro(pplayer->base.x+ 31,
-                                            pplayer->base.y - 64,
-                                            BOUNCE);
-                              trybumpbadguy(pplayer->base.x+ 31,
-                                            pplayer->base.y - 96);
-
-                              if (isfullbox(pplayer->base.x+ 31, pplayer->base.y - 32))
-                                {
-                                  bumpbrick(pplayer->base.x+ 31, pplayer->base.y - 32);
-                                }
-
-                              trybreakbrick(pplayer->base.x+ 31,
-                                            pplayer->base.y - 32);
-                              tryemptybox(pplayer->base.x+ 31,
-                                          pplayer->base.y - 32);
-                            }
-                        }
-                      else /* ducking */
-                        {
-                          if (isbrick(pplayer->base.x, pplayer->base.y) ||
-                              isfullbox(pplayer->base.x, pplayer->base.y))
-                            {
-                              trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
-                              trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
-                              if (isfullbox(pplayer->base.x, pplayer->base.y))
-                                bumpbrick(pplayer->base.x, pplayer->base.y);
-                              trybreakbrick(pplayer->base.x, pplayer->base.y);
-                              tryemptybox(pplayer->base.x, pplayer->base.y);
-                            }
+      if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
+          shape(pplayer->base.x, pplayer->base.y) == 'y')
+        {
+          add_bouncy_distro(((pplayer->base.x+ 1)
+                             / 32) * 32,
+                            (int)(pplayer->base.y / 32) * 32);
 
-                          if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
-                              isfullbox(pplayer->base.x+ 31, pplayer->base.y))
-                            {
-                              trygrabdistro(pplayer->base.x+ 31,
-                                            pplayer->base.y - 32,
-                                            BOUNCE);
-                              trybumpbadguy(pplayer->base.x+ 31,
-                                            pplayer->base.y - 64);
-                              if (isfullbox(pplayer->base.x+ 31, pplayer->base.y))
-                                bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
-                              trybreakbrick(pplayer->base.x+ 31, pplayer->base.y);
-                              tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
-                            }
-                        }
-                    }
-                  else
-                    {
-                      /* It's a brick and we're small, make the brick
-                         bounce, and grab any distros above it: */
+          if (counting_distros == NO)
+            {
+              counting_distros = YES;
+              distro_counter = 100;
+            }
 
-                      if (isbrick(pplayer->base.x, pplayer->base.y) ||
-                          isfullbox(pplayer->base.x, pplayer->base.y))
-                        {
-                          trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
-                          trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
-                          bumpbrick(pplayer->base.x, pplayer->base.y);
-                          tryemptybox(pplayer->base.x, pplayer->base.y);
-                        }
+          if (distro_counter <= 0)
+            level_change(&current_level,pplayer->base.x,pplayer->base.y, 'a');
 
-                      if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
-                          isfullbox(pplayer->base.x+ 31, pplayer->base.y))
-                        {
-                          trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
-                          trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
-                          bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
-                          tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
-                        }
+          play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
+          score = score + SCORE_DISTRO;
+          distros++;
+        }
+      else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
+               shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
+        {
+          add_bouncy_distro(((pplayer->base.x+ 1 + 31)
+                             / 32) * 32,
+                            (int)(pplayer->base.y / 32) * 32);
 
+          if (counting_distros == NO)
+            {
+              counting_distros = YES;
+              distro_counter = 100;
+            }
 
-                      /* Get a distro from a brick? */
+          if (distro_counter <= 0)
+            level_change(&current_level,pplayer->base.x+ 31, pplayer->base.y, 'a');
 
-                      if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
-                          shape(pplayer->base.x, pplayer->base.y) == 'y')
-                        {
-                          add_bouncy_distro(((pplayer->base.x+ 1)
-                                             / 32) * 32,
-                                            (int)(pplayer->base.y / 32) * 32);
+          play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
+          score = score + SCORE_DISTRO;
+          distros++;
+        }
+      }
 
-                          if (counting_distros == NO)
-                            {
-                              counting_distros = YES;
-                              distro_counter = 100;
-                            }
 
-                          if (distro_counter <= 0)
-                            level_change(&current_level,pplayer->base.x, pplayer->base.y, 'a');
+      /* Bump head: * /
 
-                          play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
-                          score = score + SCORE_DISTRO;
-                          distros++;
-                        }
-                      else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
-                               shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
-                        {
-                          add_bouncy_distro(((pplayer->base.x+ 1 + 31)
-                                             / 32) * 32,
-                                            (int)(pplayer->base.y / 32) * 32);
+      pplayer->base.y = (int)(pplayer->base.y / 32) * 32 + 30;
+      }
+      else
+      {
+      /* Land on feet: * /
 
-                          if (counting_distros == NO)
-                            {
-                              counting_distros = YES;
-                              distro_counter = 100;
-                            }
+      pplayer->base.y = (int)(pplayer->base.y / 32) * 32 - 32;
+      }
 
-                          if (distro_counter <= 0)
-                            level_change(&current_level,pplayer->base.x+ 31 + scroll_x, pplayer->base.y, 'a');
+      pplayer->base.ym = 0;
+      pplayer->jumping = NO;
+      timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
+      }*/
+    }
+}
 
-                          play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
-                          score = score + SCORE_DISTRO;
-                          distros++;
-                        }
-                    }
 
 
-                  /* Bump head: */
+player_grabdistros(pplayer);
 
-                  pplayer->base.y = (int)(pplayer->base.y / 32) * 32 + 30;
-                }
-              else
-                {
-                  /* Land on feet: */
 
-                  pplayer->base.y = (int)(pplayer->base.y / 32) * 32 - 32;
-                }
+/* Slow down horizontally: */
 
-              pplayer->base.ym = 0;
-              pplayer->jumping = NO;
-              /*pplayer->jump_counter = MAX_JUMP_COUNT;*/
-              /*timer_init(&pplayer->jump_timer);*/
-              timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
-            }
-        }
-    }
+if (!pplayer->dying)
+  {
+    if (pplayer->input.right == UP && pplayer->input.left == UP)
+      {
+        if (isice(pplayer->base.x, pplayer->base.y + 32) ||
+            !issolid(pplayer->base.x, pplayer->base.y + 32))
+          {
+            /* Slowly on ice or in air: */
 
+            if (pplayer->base.xm > 0)
+              pplayer->base.xm--;
+            else if (pplayer->base.xm < 0)
+              pplayer->base.xm++;
+          }
+        else
+          {
+            /* Quickly, otherwise: */
 
+            pplayer->base.xm = pplayer->base.xm / 2;
+          }
+      }
 
-  player_grabdistros(pplayer);
 
+    /* Drop vertically: */
 
-  /* Slow down horizontally: */
+    if (!issolid(pplayer->base.x, pplayer->base.y + 32))
+      {
+        pplayer->base.ym = pplayer->base.ym + GRAVITY;
 
-  if (!pplayer->dying)
-    {
-      if (pplayer->input.right == UP && pplayer->input.left == UP)
-        {
-          if (isice(pplayer->base.x, pplayer->base.y + 32) ||
-              !issolid(pplayer->base.x, pplayer->base.y + 32))
-            {
-              /* Slowly on ice or in air: */
+        if (pplayer->base.ym > MAX_YM)
+          pplayer->base.ym = MAX_YM;
+      }
+  }
 
-              if (pplayer->base.xm > 0)
-                pplayer->base.xm--;
-              else if (pplayer->base.xm < 0)
-                pplayer->base.xm++;
-            }
-          else
-            {
-              /* Quickly, otherwise: */
 
-              pplayer->base.xm = pplayer->base.xm / 2;
-            }
-        }
 
+timer_check(&pplayer->safe_timer);
 
-      /* Drop vertically: */
 
-      if (!issolid(pplayer->base.x, pplayer->base.y + 32))
-        {
-          pplayer->base.ym = pplayer->base.ym + GRAVITY;
+/* ---- DONE HANDLING TUX! --- */
 
-          if (pplayer->base.ym > MAX_YM)
-            pplayer->base.ym = MAX_YM;
-        }
-    }
+/* Handle invincibility timer: */
 
 
+if (current_music == HERRING_MUSIC && !timer_check(&pplayer->invincible_timer))
+  {
+    /*
+       no, we are no more invincible
+       or we were not in invincible mode
+       but are we in hurry ?
+     */
 
-  if (pplayer->safe > 0)
-    pplayer->safe--;
 
-  /* ---- DONE HANDLING TUX! --- */
+    if (timer_get_left(&time_left) < TIME_WARNING)
+      {
+        /* yes, we are in hurry
+           stop the herring_song, prepare to play the correct
+           fast level_song !
+         */
+        current_music = HURRYUP_MUSIC;
+      }
+    else
+      {
+        current_music = LEVEL_MUSIC;
+      }
 
-  /* Handle invincibility timer: */
+    /* stop the old music if it's being played */
+    if (playing_music())
+      halt_music();
+  }
 
+/* Handle skidding: */
 
-  if (timer_check(&pplayer->invincible_timer))
-    {
-      if (current_music == HERRING_MUSIC)
-        {
-          if (current_level.time_left <= TIME_WARNING)
-            {
-              /* stop the herring_song, prepare to play the correct
-               * fast level_song !
-               */
-              current_music = HURRYUP_MUSIC;
-            }
-          else
-            {
-              current_music = LEVEL_MUSIC;
-            }
-          /* stop the old music if it's being played */
-          if (playing_music())
-            halt_music();
-        }
-    }
-
-  /* Handle skidding: */
+timer_check(&pplayer->skidding_timer);
 
-  if (pplayer->skidding > 0)
-    {
-      pplayer->skidding--;
-    }
+/* End of level? */
 
-  /* End of level? */
-
-  if (pplayer->base.x>= endpos && endpos != 0)
-    {
-      next_level = 1;
-    }
+if (pplayer->base.x - scroll_x >= endpos && endpos != 0)
+  {
+    next_level = 1;
+  }
 
 }
 
-void player_input(player_type *pplayer)
+void player_handle_horizontal_input(player_type *pplayer, int dir)
 {
-  /* Handle key and joystick state: */
-
-
-  if (pplayer->input.right == DOWN && pplayer->input.left == UP)
+  if (pplayer->jumping == NO)
     {
-      if (pplayer->jumping == NO)
+      if ((dir ? (pplayer->base.xm < -SKID_XM) : (pplayer->base.xm > SKID_XM)) && !timer_started(&pplayer->skidding_timer) &&
+          pplayer->dir == !dir)
         {
-          if (pplayer->base.xm < -SKID_XM && !pplayer->skidding &&
-              pplayer->dir == LEFT)
-            {
-              pplayer->skidding = SKID_TIME;
+          timer_start(&pplayer->skidding_timer, SKID_TIME);
 
-              play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
+          play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
 
-            }
-          pplayer->dir = RIGHT;
         }
+      pplayer->dir = dir;
+    }
 
-      if (pplayer->base.xm < 0 && !isice(pplayer->base.x, pplayer->base.y + 32) &&
-          !pplayer->skidding)
-        {
-          pplayer->base.xm = 0;
-        }
+  if ((dir ? (pplayer->base.xm < 0) : (pplayer->base.xm > 0)) && !isice(pplayer->base.x, pplayer->base.y + 32) &&
+      !timer_started(&pplayer->skidding_timer))
+    {
+      pplayer->base.xm = 0;
+    }
 
-      if (!pplayer->duck)
+  if (!pplayer->duck)
+    {
+      if (pplayer->dir == dir)
         {
-          if (pplayer->dir == RIGHT)
+          /* Facing the direction we're jumping?  Go full-speed: */
+
+          if (pplayer->input.fire == UP)
             {
-              /* Facing the direction we're jumping?  Go full-speed: */
+              pplayer->base.xm = pplayer->base.xm + ( dir ? WALK_SPEED : -WALK_SPEED) * frame_ratio;
 
-              if (pplayer->input.fire == UP)
+              if(dir)
                 {
-                  pplayer->base.xm = pplayer->base.xm + RUN_SPEED;
+                  if (pplayer->base.xm > MAX_WALK_XM)
+                    pplayer->base.xm = MAX_WALK_XM;
+                }
+              else
+                {
+                  if (pplayer->base.xm < -MAX_WALK_XM)
+                    pplayer->base.xm = -MAX_WALK_XM;
+                }
+            }
+          else if ( pplayer->input.fire == DOWN)
+            {
+              pplayer->base.xm = pplayer->base.xm + ( dir ? RUN_SPEED : -RUN_SPEED) * frame_ratio;
 
+              if(dir)
+                {
                   if (pplayer->base.xm > MAX_RUN_XM)
                     pplayer->base.xm = MAX_RUN_XM;
                 }
-              else if ( pplayer->input.fire == DOWN)
+              else
                 {
-                  pplayer->base.xm = pplayer->base.xm + WALK_SPEED;
-
-                  if (pplayer->base.xm > MAX_WALK_XM)
-                    pplayer->base.xm = MAX_WALK_XM;
+                  if (pplayer->base.xm < -MAX_RUN_XM)
+                    pplayer->base.xm = -MAX_RUN_XM;
                 }
             }
           else
@@ -459,114 +623,92 @@ void player_input(player_type *pplayer)
               /* Not facing the direction we're jumping?
               Go half-speed: */
 
-              pplayer->base.xm = pplayer->base.xm + WALK_SPEED / 2;
+              pplayer->base.xm = pplayer->base.xm + ( dir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio;
 
-              if (pplayer->base.xm > MAX_WALK_XM / 2)
-                pplayer->base.xm = MAX_WALK_XM / 2;
+              if(dir)
+                {
+                  if (pplayer->base.xm > MAX_WALK_XM / 2)
+                    pplayer->base.xm = MAX_WALK_XM / 2;
+                }
+              else
+                {
+                  if (pplayer->base.xm < -MAX_WALK_XM / 2)
+                    pplayer->base.xm = -MAX_WALK_XM / 2;
+                }
             }
         }
+
     }
-  else if (pplayer->input.left == DOWN && pplayer->input.right == UP)
+}
+
+void player_handle_vertical_input(player_type *pplayer)
+{
+  if(!timer_started(&pplayer->jump_timer))
     {
-      if (pplayer->jumping == NO)
-        {
-          if (pplayer->base.xm > SKID_XM && !pplayer->skidding &&
-              pplayer->dir == RIGHT)
-            {
-              pplayer->skidding = SKID_TIME;
-              play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
-            }
-          pplayer->dir = LEFT;
-        }
+      timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
 
-      if (pplayer->base.xm > 0 && !isice(pplayer->base.x, pplayer->base.y + 32) &&
-          !pplayer->skidding)
-        {
-          pplayer->base.xm = 0;
-        }
 
-      if (!pplayer->duck)
-        {
-          if (pplayer->dir == LEFT)
-            {
-              /* Facing the direction we're jumping?  Go full-speed: */
+      /* Taking off? */
 
-              if (pplayer->input.fire == UP)
-                {
-                  pplayer->base.xm = pplayer->base.xm - RUN_SPEED;
+      if (!issolid(pplayer->base.x, pplayer->base.y + 32) ||
+          pplayer->base.ym != 0)
+        {
+          /* If they're not on the ground, or are currently moving
+          vertically, don't jump! */
 
-                  if (pplayer->base.xm < -MAX_RUN_XM)
-                    pplayer->base.xm = -MAX_RUN_XM;
-                }
-              else if (pplayer->input.fire == DOWN)
-                {
-                  pplayer->base.xm = pplayer->base.xm - WALK_SPEED;
+          pplayer->jumping = NO;
+          timer_stop(&pplayer->jump_timer);
+        }
+      else
+        {
+          /* Make sure we're not standing back up into a solid! */
 
-                  if (pplayer->base.xm < -MAX_WALK_XM)
-                    pplayer->base.xm = -MAX_WALK_XM;
-                }
-            }
-          else
+          if (pplayer->size == SMALL || pplayer->duck == NO ||
+              !issolid(pplayer->base.x, pplayer->base.y))
             {
-              /* Not facing the direction we're jumping?
-              Go half-speed: */
+              pplayer->jumping = YES;
 
-              pplayer->base.xm = pplayer->base.xm - WALK_SPEED / 2;
-
-              if (pplayer->base.xm < -MAX_WALK_XM / 2)
-                pplayer->base.xm = -MAX_WALK_XM / 2;
+              if (pplayer->size == SMALL)
+                play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
+              else
+                play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
             }
         }
     }
 
-  /* Jump/jumping? */
+  /* Keep jumping for a while: */
 
-  if ( pplayer->input.up == DOWN)
+  if (timer_check(&pplayer->jump_timer))
     {
-      if(!timer_started(&pplayer->jump_timer))
-        {
-          timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
-
-
-          /* Taking off? */
-
-          if (!issolid(pplayer->base.x, pplayer->base.y + 32) ||
-              pplayer->base.ym != 0)
-            {
-              /* If they're not on the ground, or are currently moving
-              vertically, don't jump! */
+      pplayer->base.ym = pplayer->base.ym - JUMP_SPEED * frame_ratio;
+      if (pplayer->base.ym < -YM_FOR_JUMP)
+        pplayer->base.ym = -YM_FOR_JUMP;
+    }
+}
 
-              pplayer->jumping = NO;
-              timer_stop(&pplayer->jump_timer);
-            }
-          else
-            {
-              /* Make sure we're not standing back up into a solid! */
+void player_input(player_type *pplayer)
+{
+  /* Handle key and joystick state: */
 
-              if (pplayer->size == SMALL || pplayer->duck == NO ||
-                  !issolid(pplayer->base.x, pplayer->base.y))
-                {
-                  pplayer->jumping = YES;
 
-                  if (pplayer->size == SMALL)
-                    play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
-                  else
-                    play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
-                }
-            }
-        }
+  if (pplayer->input.right == DOWN && pplayer->input.left == UP)
+    {
+      player_handle_horizontal_input(pplayer,RIGHT);
+    }
+  else if (pplayer->input.left == DOWN && pplayer->input.right == UP)
+    {
+      player_handle_horizontal_input(pplayer,LEFT);
+    }
 
-      /* Keep jumping for a while: */
+  /* Jump/jumping? */
 
-      if (timer_check(&pplayer->jump_timer))
-        {
-          pplayer->base.ym = pplayer->base.ym - JUMP_SPEED;
-        }
+  if ( pplayer->input.up == DOWN)
+    {
+      player_handle_vertical_input(pplayer);
     }
   else
     timer_stop(&pplayer->jump_timer);
 
-
   /* Shoot! */
 
   if (pplayer->input.fire == DOWN && pplayer->input.old_fire == UP && pplayer->got_coffee)
@@ -646,8 +788,7 @@ void player_grabdistros(player_type *pplayer)
 
 void player_draw(player_type* pplayer)
 {
-
-  if (pplayer->safe == 0 || (frame % 2) == 0)
+  if (!timer_started(&pplayer->safe_timer) || (frame % 2) == 0)
     {
       if (pplayer->size == SMALL)
         {
@@ -704,13 +845,13 @@ void player_draw(player_type* pplayer)
               if (pplayer->dir == RIGHT)
                 {
                   texture_draw(&bigcape_right[frame % 2],
-                               pplayer->base.x- scroll_x - 8 - 16, pplayer->base.y - 32,
+                               pplayer->base.x- scroll_x, pplayer->base.y,
                                NO_UPDATE);
                 }
               else
                 {
                   texture_draw(&bigcape_left[frame % 2],
-                               pplayer->base.x-scroll_x - 8, pplayer->base.y - 32,
+                               pplayer->base.x-scroll_x, pplayer->base.y,
                                NO_UPDATE);
                 }
             }
@@ -719,20 +860,20 @@ void player_draw(player_type* pplayer)
             {
               if (!pplayer->duck)
                 {
-                  if (!pplayer->skidding)
+                  if (!timer_started(&pplayer->skidding_timer))
                     {
                       if (!pplayer->jumping || pplayer->base.ym > 0)
                         {
                           if (pplayer->dir == RIGHT)
                             {
                               texture_draw(&bigtux_right[pplayer->frame],
-                                           pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                           pplayer->base.x- scroll_x, pplayer->base.y,
                                            NO_UPDATE);
                             }
                           else
                             {
                               texture_draw(&bigtux_left[pplayer->frame],
-                                           pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                           pplayer->base.x- scroll_x, pplayer->base.y,
                                            NO_UPDATE);
                             }
                         }
@@ -741,13 +882,13 @@ void player_draw(player_type* pplayer)
                           if (pplayer->dir == RIGHT)
                             {
                               texture_draw(&bigtux_right_jump,
-                                           pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                           pplayer->base.x- scroll_x, pplayer->base.y,
                                            NO_UPDATE);
                             }
                           else
                             {
                               texture_draw(&bigtux_left_jump,
-                                           pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                           pplayer->base.x- scroll_x, pplayer->base.y,
                                            NO_UPDATE);
                             }
                         }
@@ -757,13 +898,13 @@ void player_draw(player_type* pplayer)
                       if (pplayer->dir == RIGHT)
                         {
                           texture_draw(&skidtux_right,
-                                       pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                       pplayer->base.x- scroll_x, pplayer->base.y,
                                        NO_UPDATE);
                         }
                       else
                         {
                           texture_draw(&skidtux_left,
-                                       pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                       pplayer->base.x- scroll_x, pplayer->base.y,
                                        NO_UPDATE);
                         }
                     }
@@ -772,12 +913,12 @@ void player_draw(player_type* pplayer)
                 {
                   if (pplayer->dir == RIGHT)
                     {
-                      texture_draw(&ducktux_right, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16,
+                      texture_draw(&ducktux_right, pplayer->base.x- scroll_x, pplayer->base.y,
                                    NO_UPDATE);
                     }
                   else
                     {
-                      texture_draw(&ducktux_left, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16,
+                      texture_draw(&ducktux_left, pplayer->base.x- scroll_x, pplayer->base.y,
                                    NO_UPDATE);
                     }
                 }
@@ -788,20 +929,20 @@ void player_draw(player_type* pplayer)
 
               if (!pplayer->duck)
                 {
-                  if (!pplayer->skidding)
+                  if (!timer_started(&pplayer->skidding_timer))
                     {
                       if (!pplayer->jumping || pplayer->base.ym > 0)
                         {
                           if (pplayer->dir == RIGHT)
                             {
                               texture_draw(&bigfiretux_right[pplayer->frame],
-                                           pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                           pplayer->base.x- scroll_x, pplayer->base.y,
                                            NO_UPDATE);
                             }
                           else
                             {
                               texture_draw(&bigfiretux_left[pplayer->frame],
-                                           pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                           pplayer->base.x- scroll_x, pplayer->base.y,
                                            NO_UPDATE);
                             }
                         }
@@ -810,13 +951,13 @@ void player_draw(player_type* pplayer)
                           if (pplayer->dir == RIGHT)
                             {
                               texture_draw(&bigfiretux_right_jump,
-                                           pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                           pplayer->base.x- scroll_x, pplayer->base.y,
                                            NO_UPDATE);
                             }
                           else
                             {
                               texture_draw(&bigfiretux_left_jump,
-                                           pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                           pplayer->base.x- scroll_x, pplayer->base.y,
                                            NO_UPDATE);
                             }
                         }
@@ -826,13 +967,13 @@ void player_draw(player_type* pplayer)
                       if (pplayer->dir == RIGHT)
                         {
                           texture_draw(&skidfiretux_right,
-                                       pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                       pplayer->base.x- scroll_x, pplayer->base.y,
                                        NO_UPDATE);
                         }
                       else
                         {
                           texture_draw(&skidfiretux_left,
-                                       pplayer->base.x- scroll_x - 8, pplayer->base.y - 32,
+                                       pplayer->base.x- scroll_x, pplayer->base.y,
                                        NO_UPDATE);
                         }
                     }
@@ -841,19 +982,18 @@ void player_draw(player_type* pplayer)
                 {
                   if (pplayer->dir == RIGHT)
                     {
-                      texture_draw(&duckfiretux_right, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16,
+                      texture_draw(&duckfiretux_right, pplayer->base.x- scroll_x, pplayer->base.y,
                                    NO_UPDATE);
                     }
                   else
                     {
-                      texture_draw(&duckfiretux_left, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16,
+                      texture_draw(&duckfiretux_left, pplayer->base.x- scroll_x, pplayer->base.y,
                                    NO_UPDATE);
                     }
                 }
             }
         }
     }
-
 }
 
 void player_collision(player_type* pplayer, void* p_c_object, int c_object)
@@ -863,11 +1003,11 @@ void player_collision(player_type* pplayer, void* p_c_object, int c_object)
   switch (c_object)
     {
     case CO_BADGUY:
-      pbad_c = p_c_object;
+      pbad_c = (bad_guy_type*) p_c_object;
       /* Hurt the player if he just touched it: */
 
       if (!pbad_c->dying && !pplayer->dying &&
-          !pplayer->safe &&
+          !timer_started(&pplayer->safe_timer) &&
           pbad_c->mode != HELD)
         {
           if (pbad_c->mode == FLAT  && pplayer->input.fire != DOWN)
@@ -938,8 +1078,10 @@ void player_collision(player_type* pplayer, void* p_c_object, int c_object)
                   play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
                 }
             }
+          score_multiplier++;
         }
-      score_multiplier++;
+      break;
+    default:
       break;
     }
 
@@ -955,7 +1097,7 @@ void player_kill(player_type* pplayer, int mode)
 
   if (pplayer->dir == RIGHT)
     pplayer->base.xm = -8;
-  else if (tux.dir == LEFT)
+  else if (pplayer->dir == LEFT)
     pplayer->base.xm = 8;
 
   if (mode == SHRINK && pplayer->size == BIG)
@@ -964,8 +1106,9 @@ void player_kill(player_type* pplayer, int mode)
         pplayer->got_coffee = NO;
 
       pplayer->size = SMALL;
+      pplayer->base.height = 32;
 
-      pplayer->safe = TUX_SAFE_TIME;
+      timer_start(&pplayer->safe_timer,TUX_SAFE_TIME);
     }
   else
     {
@@ -981,7 +1124,9 @@ void player_dying(player_type *pplayer)
 
   --pplayer->lives;
   player_remove_powerups(pplayer);
-  pplayer->dying = 0;
+  pplayer->dying = NO;
+
+  player_level_begin(pplayer);
 
 }
 
@@ -990,6 +1135,7 @@ void player_remove_powerups(player_type* pplayer)
 {
   pplayer->got_coffee = NO;
   pplayer->size = SMALL;
+  pplayer->base.height = 32;
 }
 
 void player_keep_in_bounds(player_type* pplayer)