update
[supertux.git] / src / badguy.c
index 5085695..29f19c1 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 img_bsod_squished_left, img_bsod_squished_right,
+img_bsod_falling_left, img_bsod_falling_right,
+img_laptop_flat_left, img_laptop_flat_right,
+img_laptop_falling_left, img_laptop_falling_right;
+texture_type img_bsod_left[4], img_bsod_right[4],
+img_laptop_left[3], img_laptop_right[3],
+img_money_left[2], img_money_right[2];
+bitmask *bm_bsod;
+
 void badguy_create_bitmasks()
 {
   /*bm_bsod = img_bsod_left[0];*/
 }
 
-void badguy_init(bad_guy_type* pbad)
+void badguy_init(bad_guy_type* pbad, float x, float y, int kind)
 {
-  pbad->base.updated = SDL_GetTicks();
-  pbad->base.alive = NO;
   pbad->base.width = 32;
   pbad->base.height = 32;
-
+  pbad->base.alive = YES;
+  pbad->mode = NORMAL;
+  pbad->dying = NO;
+  pbad->kind = kind;
+  pbad->base.x = x;
+  pbad->base.y = y;
+  pbad->base.xm = 1.3;
+  pbad->base.ym = 4.8;
+  pbad->old_base = pbad->base;
+  pbad->dir = LEFT;
+  pbad->seen = NO;
+  timer_init(&pbad->timer,YES);
+  physic_init(&pbad->physic);
 }
 
 void badguy_action(bad_guy_type* pbad)
 {
 
-  double frame_ratio = get_frame_ratio(&pbad->base);
-
   if (pbad->base.alive)
     {
       if (pbad->seen)
@@ -59,23 +76,38 @@ void badguy_action(bad_guy_type* pbad)
 
               pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio;
 
+              if (pbad->dying != FALLING)
+                collision_swept_object_map(&pbad->old_base,&pbad->base);
+              if (pbad->base.y > screen->h)
+                pbad->base.alive = NO;
 
               /* Bump into things horizontally: */
 
               if (!pbad->dying)
                 {
-                  if (issolid(pbad->base.x, pbad->base.y))
-                    pbad->dir = !pbad->dir;
+                  if (issolid( pbad->base.x, (int) pbad->base.y + 16))
+                    {
+                      pbad->dir = RIGHT;
+                    }
+                  else if (issolid( pbad->base.x + pbad->base.width, (int) pbad->base.y + 16))
+                    {
+                      pbad->dir = LEFT;
+                    }
                 }
 
               /* Fall if we get off the ground: */
 
               if (pbad->dying != FALLING)
                 {
-                  if (!issolid(pbad->base.x, pbad->base.y + 32) &&
-                      pbad->base.ym < MAX_YM)
+                  if (!issolid(pbad->base.x+16, pbad->base.y + 32))
                     {
-                      pbad->base.ym = pbad->base.ym + GRAVITY;
+                      if(!physic_is_set(&pbad->physic))
+                        {
+                          physic_set_state(&pbad->physic,PH_VT);
+                          physic_set_start_vy(&pbad->physic,2.);
+                        }
+
+                      pbad->base.ym = physic_get_velocity(&pbad->physic);
                     }
                   else
                     {
@@ -86,10 +118,18 @@ void badguy_action(bad_guy_type* pbad)
                           pbad->base.y = (int)(pbad->base.y / 32) * 32;
                           pbad->base.ym = 0;
                         }
+                      physic_init(&pbad->physic);
                     }
                 }
               else
-                pbad->base.ym = pbad->base.ym + GRAVITY;
+                {
+                  if(!physic_is_set(&pbad->physic))
+                    {
+                      physic_set_state(&pbad->physic,PH_VT);
+                      physic_set_start_vy(&pbad->physic,2.);
+                    }
+                  pbad->base.ym = physic_get_velocity(&pbad->physic);
+                }
 
               if (pbad->base.y > screen->h)
                 pbad->base.alive = NO;
@@ -100,7 +140,7 @@ void badguy_action(bad_guy_type* pbad)
 
               /* Move left/right: */
 
-              if (pbad->mode != KICK && pbad->mode != HELD)
+              if (pbad->mode == NORMAL || pbad->mode == KICK)
                 {
                   if (pbad->dying == NO ||
                       pbad->dying == FALLING)
@@ -111,31 +151,33 @@ void badguy_action(bad_guy_type* pbad)
                         pbad->base.x = pbad->base.x - pbad->base.xm * frame_ratio;
                     }
                 }
-              else if (pbad->mode == KICK)
-                {
-               /* Obsolete
-                  if (pbad->dir == RIGHT)
-                    pbad->base.x = pbad->base.x + 16;
-                  else if (pbad->dir == LEFT)
-                    pbad->base.x = pbad->base.x - 16;*/
-                }
               else if (pbad->mode == HELD)
                 { /* FIXME: The pbad object shouldn't know about pplayer objects. */
                   /* If we're holding the laptop */
-                  if(tux.dir==RIGHT)
+                  pbad->dir=tux.dir;
+                  if(pbad->dir==RIGHT)
                     {
-                      pbad->base.x = tux.base.x - 16;
-                      pbad->base.y = tux.base.y - 8 - (tux.size*16);
+                      pbad->base.x = tux.base.x + 16;
+                      pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height;
                     }
                   else /* facing left */
                     {
                       pbad->base.x = tux.base.x - 16;
-                      pbad->base.y = tux.base.y - 8 - (tux.size*16);
+                      pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height;
+                    }
+                  if(collision_object_map(&pbad->base))
+                    {
+                      pbad->base.x = tux.base.x;
+                      pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height;
                     }
 
                   if(tux.input.fire != DOWN) /* SHOOT! */
                     {
-                      pbad->dir=tux.dir;
+                      if(pbad->dir == LEFT)
+                        pbad->base.x -= 24;
+                      else
+                        pbad->base.x += 24;
+
                       pbad->mode=KICK;
                       pbad->base.ym-=8;
                       play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER);
@@ -148,26 +190,37 @@ void badguy_action(bad_guy_type* pbad)
               if(pbad->mode != HELD)
                 pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio;
 
+              if (pbad->dying != FALLING)
+                collision_swept_object_map(&pbad->old_base,&pbad->base);
+              if (pbad->base.y > screen->h)
+                pbad->base.alive = NO;
+              /* Bump into things horizontally: */
+
               /* Bump into things horizontally: */
 
               if (!pbad->dying)
                 {
-                  if (issolid(pbad->base.x, pbad->base.y))
+                  int changed = pbad->dir;
+                  if (issolid( pbad->base.x, (int) pbad->base.y + 16))
                     {
-                      pbad->dir = !pbad->dir;
-
-                      if (pbad->mode == KICK)
-                        {
-                          /* handle stereo sound */
-                          /* FIXME: In theory a badguy object doesn't know anything about player objects */
-                          if (tux.base.x  > pbad->base.x)
-                            play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
-                          else if (tux.base.x  < pbad->base.x)
-                            play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
-                          else
-                            play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
-                        }
+                      pbad->dir = RIGHT;
                     }
+                  else if (issolid( pbad->base.x + pbad->base.width, (int) pbad->base.y + 16))
+                    {
+                      pbad->dir = LEFT;
+                    }
+                  if(pbad->mode == KICK && changed != pbad->dir)
+                    {
+                      /* handle stereo sound */
+                      /* FIXME: In theory a badguy object doesn't know anything about player objects */
+                      if (tux.base.x  > pbad->base.x)
+                        play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
+                      else if (tux.base.x  < pbad->base.x)
+                        play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
+                      else
+                        play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
+                    }
+
                 }
 
 
@@ -175,11 +228,18 @@ void badguy_action(bad_guy_type* pbad)
 
               if (pbad->dying != FALLING)
                 {
-                  if (!issolid(pbad->base.x, pbad->base.y + 32) &&
-                      pbad->base.ym < MAX_YM)
+                  if (!issolid(pbad->base.x+16, pbad->base.y + 32))
                     {
+                      if(!physic_is_set(&pbad->physic))
+                        {
+                          physic_set_state(&pbad->physic,PH_VT);
+                          physic_set_start_vy(&pbad->physic,0.);
+                        }
+
                       if(pbad->mode != HELD)
-                        pbad->base.ym = pbad->base.ym + GRAVITY;
+                        {
+                          pbad->base.ym = physic_get_velocity(&pbad->physic);
+                        }
                     }
                   else
                     {
@@ -190,13 +250,20 @@ void badguy_action(bad_guy_type* pbad)
                           pbad->base.y = (int)(pbad->base.y / 32) * 32;
                           pbad->base.ym = 0;
                         }
+                      physic_init(&pbad->physic);
                     }
                 }
               else
-                pbad->base.ym = pbad->base.ym + GRAVITY;
+                {
+                  if(!physic_is_set(&pbad->physic))
+                    {
+                      physic_set_state(&pbad->physic,PH_VT);
+                      physic_set_start_vy(&pbad->physic,0.);
+                    }
+                  pbad->base.ym = physic_get_velocity(&pbad->physic);
+                }
+
 
-              if (pbad->base.y > screen->h)
-                pbad->base.alive = NO;
             }
           else if (pbad->kind == BAD_MONEY)
             {
@@ -205,36 +272,49 @@ void badguy_action(bad_guy_type* pbad)
 
               /* Move vertically: */
 
-              pbad->base.y = pbad->base.y + pbad->base.ym *frame_ratio;
+              pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio;
 
+              if (pbad->dying != FALLING)
+                collision_swept_object_map(&pbad->old_base,&pbad->base);
 
-              /* Fall if we get off the ground: */
+              if (pbad->base.y > screen->h)
+                pbad->base.alive = NO;
+
+              if(physic_get_state(&pbad->physic) == -1)
+                {
+                  physic_set_state(&pbad->physic,PH_VT);
+                  physic_set_start_vy(&pbad->physic,0.);
+                }
 
               if (pbad->dying != FALLING)
                 {
-                  if (!issolid(pbad->base.x, pbad->base.y + 32))
+                  if(issolid(pbad->base.x, pbad->base.y + 32))
                     {
-                      if (pbad->base.ym < MAX_YM)
-                        {
-                          pbad->base.ym = pbad->base.ym + GRAVITY;
-                        }
+                      physic_set_state(&pbad->physic,PH_VT);
+                      physic_set_start_vy(&pbad->physic,6.);
+                      pbad->base.ym = physic_get_velocity(&pbad->physic);
+                    }
+                  else if(issolid(pbad->base.x, pbad->base.y))
+                    { /* This works, but isn't the best solution imagineable */
+                      physic_set_state(&pbad->physic,PH_VT);
+                      physic_set_start_vy(&pbad->physic,0.);
+                      pbad->base.ym = physic_get_velocity(&pbad->physic);
+                      ++pbad->base.y;
                     }
                   else
                     {
-                      /* Land: */
-
-                      if (pbad->base.ym > 0)
-                        {
-                          pbad->base.y = (int)(pbad->base.y / 32) * 32;
-                          pbad->base.ym = -MAX_YM;
-                        }
+                      pbad->base.ym = physic_get_velocity(&pbad->physic);
                     }
                 }
               else
-                pbad->base.ym = pbad->base.ym + GRAVITY;
-
-              if (pbad->base.y > screen->h)
-                pbad->base.alive = NO;
+                {
+                  if(!physic_is_set(&pbad->physic))
+                    {
+                      physic_set_state(&pbad->physic,PH_VT);
+                      physic_set_start_vy(&pbad->physic,0.);
+                    }
+                  pbad->base.ym = physic_get_velocity(&pbad->physic);
+                }
             }
           else if (pbad->kind == -1)
           {}
@@ -248,16 +328,18 @@ void badguy_action(bad_guy_type* pbad)
 
   /* Handle mode timer: */
 
-  if (pbad->mode == FLAT /* && bad_guys[1].mode != HELD*/)
+  if (pbad->mode == FLAT && pbad->mode != HELD)
     {
       if(!timer_check(&pbad->timer))
+      {
         pbad->mode = NORMAL;
+        pbad->base.xm = 4;
+        }
+    }
+  else if (pbad->mode == KICK)
+    {
+      timer_check(&pbad->timer);
     }
-  /* else if (pbad->mode == KICK)
-     {
-       if (pbad->timer > 0)
-         pbad->timer--;
-     }*/
 
 
   /* Handle dying timer: */
@@ -421,7 +503,7 @@ void badguy_draw(bad_guy_type* pbad)
         }
       else if (pbad->kind == BAD_MONEY)
         {
-          if (pbad->base.ym > -16)
+          if (pbad->base.ym != 300 /* > -16*/)
             {
               if (pbad->dir == LEFT)
                 {
@@ -480,14 +562,19 @@ void badguy_collision(bad_guy_type* pbad, void *p_c_object, int c_object)
       else if (pbad->kind == BAD_LAPTOP)
         add_score(pbad->base.x - scroll_x, pbad->base.y,
                   25 * score_multiplier);
+      else if (pbad->kind == BAD_MONEY)
+        add_score(pbad->base.x - scroll_x, pbad->base.y,
+                  50 * score_multiplier);
 
       /* Play death sound: */
       play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
       break;
     case CO_BADGUY:
-      pbad_c = p_c_object;
-      if (pbad->mode != KICK)
-        pbad->dir = !pbad->dir;
+      pbad_c = (bad_guy_type*) p_c_object;
+      if (pbad->mode == NORMAL)
+      {
+      /* do nothing */
+      }
       else
         {
           /* We're in kick mode, kill the other guy: */
@@ -499,57 +586,68 @@ void badguy_collision(bad_guy_type* pbad, void *p_c_object, int c_object)
           add_score(pbad->base.x - scroll_x,
                     pbad->base.y, 100);
         }
-      pbad->dir = !pbad->dir;
       break;
     case CO_PLAYER:
-      pplayer_c = p_c_object;
-      if (pbad->kind == BAD_BSOD)
+      pplayer_c = (player_type*) p_c_object;
+      if(pbad->kind != BAD_MONEY)
         {
-          pbad->dying = SQUISHED;
-          timer_start(&pbad->timer,4000);
-          pplayer_c->base.ym = -KILL_BOUNCE_YM;
+          if (pbad->kind == BAD_BSOD)
+            {
+              pbad->dying = SQUISHED;
+              timer_start(&pbad->timer,4000);
+              physic_set_state(&pplayer_c->vphysic,PH_VT);
+              physic_set_start_vy(&pplayer_c->vphysic,2.);
+             pplayer_c->base.y = pbad->base.y - pplayer_c->base.height;
 
-          add_score(pbad->base.x - scroll_x, pbad->base.y,
-                    50 * score_multiplier);
+              add_score(pbad->base.x - scroll_x, pbad->base.y,
+                        50 * score_multiplier);
 
-          play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
-        }
-      else if (pbad->kind == BAD_LAPTOP)
-        {
-          if (pbad->mode != FLAT)
+              play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
+            }
+          else if (pbad->kind == BAD_LAPTOP)
             {
-              /* Flatten! */
 
-              play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
-              pbad->mode = FLAT;
-             pbad->base.xm = 4;
+              if (pbad->mode == NORMAL || pbad->mode == KICK)
+                {
+                  /* Flatten! */
 
-              timer_start(&pbad->timer,10000);
+                  play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
+                  pbad->mode = FLAT;
+                  pbad->base.xm = 4;
 
-              pplayer_c->base.y = pplayer_c->base.y - 32;
-            }
-          else
-            {
-              /* Kick! */
+                  timer_start(&pbad->timer,10000);
 
-              pbad->mode = KICK;
-              play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
+                  physic_set_state(&pplayer_c->vphysic,PH_VT);
+                  physic_set_start_vy(&pplayer_c->vphysic,2.);
+                 pplayer_c->base.y = pbad->base.y - pplayer_c->base.height;
+                }
+              else if (pbad->mode == FLAT)
+                {
+                  /* Kick! */
 
-              if (pplayer_c->base.x <= pbad->base.x)
-                pbad->dir = RIGHT;
-              else
-                pbad->dir = LEFT;
+                  play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
 
-              timer_start(&pbad->timer,5000);
-            }
+                  if (pplayer_c->base.x <= pbad->base.x)
+                    pbad->dir = RIGHT;
+                  else
+                    pbad->dir = LEFT;
 
-          pplayer_c->base.ym = -KILL_BOUNCE_YM;
+                  pbad->base.xm = 8;
 
-          add_score(pbad->base.x - scroll_x,
-                    pbad->base.y,
-                    25 * score_multiplier);
+                  timer_start(&pbad->timer,5000);
+                }
+
+              physic_set_state(&pplayer_c->vphysic,PH_VT);
+              physic_set_start_vy(&pplayer_c->vphysic,2.);
+             pplayer_c->base.y = pbad->base.y - pplayer_c->base.height;
+             
+              add_score(pbad->base.x - scroll_x,
+                        pbad->base.y,
+                        25 * score_multiplier);
 
-          /* play_sound(sounds[SND_SQUISH]); */
+              /* play_sound(sounds[SND_SQUISH]); */
+            }
+          score_multiplier++;
         }
       break;
     }