Stay-on-platform Badguys no longer go crazy when falling down
authorChristoph Sommer <mail@christoph-sommer.de>
Mon, 10 Jul 2006 00:48:50 +0000 (00:48 +0000)
committerChristoph Sommer <mail@christoph-sommer.de>
Mon, 10 Jul 2006 00:48:50 +0000 (00:48 +0000)
SVN-Revision: 3975

src/badguy/badguy.cpp
src/badguy/badguy.hpp
src/badguy/igel.cpp
src/badguy/mrbomb.cpp
src/badguy/mriceblock.cpp
src/badguy/mrtree.cpp
src/badguy/snail.cpp
src/badguy/spiky.cpp
src/badguy/totem.cpp

index 26db65d..533a6ae 100644 (file)
@@ -34,7 +34,7 @@ static const float X_OFFSCREEN_DISTANCE = 1600;
 static const float Y_OFFSCREEN_DISTANCE = 1200;
 
 BadGuy::BadGuy(const Vector& pos, const std::string& sprite_name, int layer)
-  : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT) 
+  : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT), on_ground_flag(false) 
 {
   start_position = bbox.p1;
 
@@ -43,7 +43,7 @@ BadGuy::BadGuy(const Vector& pos, const std::string& sprite_name, int layer)
 }
 
 BadGuy::BadGuy(const Vector& pos, Direction direction, const std::string& sprite_name, int layer)
-  : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(direction), start_dir(direction), state(STATE_INIT) 
+  : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(direction), start_dir(direction), state(STATE_INIT), on_ground_flag(false)
 {
   start_position = bbox.p1;
 
@@ -52,7 +52,7 @@ BadGuy::BadGuy(const Vector& pos, Direction direction, const std::string& sprite
 }
 
 BadGuy::BadGuy(const lisp::Lisp& reader, const std::string& sprite_name, int layer)
-  : MovingSprite(reader, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT) 
+  : MovingSprite(reader, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT), on_ground_flag(false)
 {
   start_position = bbox.p1;
 
@@ -114,6 +114,8 @@ BadGuy::update(float elapsed_time)
       movement = physic.get_movement(elapsed_time);
       break;
   }
+
+  on_ground_flag = false;
 }
 
 Direction
@@ -197,8 +199,9 @@ BadGuy::collision(GameObject& other, const CollisionHit& hit)
 }
 
 void
-BadGuy::collision_solid(const CollisionHit& )
+BadGuy::collision_solid(const CollisionHit& hit)
 {
+  update_on_ground_flag(hit);
 }
 
 HitResponse
@@ -407,3 +410,16 @@ BadGuy::get_nearest_player()
 
   return 0;
 }
+
+void 
+BadGuy::update_on_ground_flag(const CollisionHit& hit)
+{
+  if (hit.bottom) on_ground_flag = true;
+}
+
+bool
+BadGuy::on_ground()
+{
+  return on_ground_flag;
+}
+
index 797cd44..44613e4 100644 (file)
@@ -165,11 +165,24 @@ protected:
    */ 
   Direction str2dir( std::string dir_str );
 
+  /**
+   * Update on_ground_flag judging by solid collision @c hit.
+   * This gets called from the base implementation of collision_solid, so call this when overriding collision_solid's default behaviour.
+   */
+  void update_on_ground_flag(const CollisionHit& hit);
+
+  /**
+   * Returns true if we touched ground in the past frame
+   * This only works if update_on_ground_flag() gets called in collision_solid.
+   */
+  bool on_ground();
+
 private:
   void try_activate();
   
   State state;
   Timer state_timer;
+  bool on_ground_flag;
 };
 
 #endif
index 02b7163..0d305e5 100644 (file)
@@ -94,7 +94,7 @@ Igel::active_update(float elapsed_time)
   switch (state) {
 
     case STATE_NORMAL:
-      if (might_fall()) {
+      if (on_ground() && might_fall()) {
        // turn around when we are at a ledge
        turn_around();
       } 
@@ -118,6 +118,8 @@ Igel::active_update(float elapsed_time)
 void
 Igel::collision_solid(const CollisionHit& hit)
 {
+  update_on_ground_flag(hit);
+
   if(hit.top || hit.bottom) { // floor or roof
     physic.set_velocity_y(0);
     return;
index d59b958..78cb5b7 100644 (file)
@@ -68,7 +68,7 @@ MrBomb::activate()
 void
 MrBomb::active_update(float elapsed_time)
 {
-  if (might_fall())
+  if (on_ground() && might_fall())
   {
     dir = (dir == LEFT ? RIGHT : LEFT);
     sprite->set_action(dir == LEFT ? "left" : "right");
@@ -90,6 +90,8 @@ MrBomb::collision_squished(Player& player)
 void
 MrBomb::collision_solid(const CollisionHit& hit)
 {
+  update_on_ground_flag(hit);
+  
   if(hit.bottom || hit.top) {
     physic.set_velocity_y(0);
   }
index aa91c5a..09f2bb0 100644 (file)
@@ -73,7 +73,7 @@ MrIceBlock::active_update(float elapsed_time)
     set_state(ICESTATE_NORMAL);
   }
 
-  if (ice_state == ICESTATE_NORMAL && might_fall(601))
+  if (ice_state == ICESTATE_NORMAL && on_ground() && might_fall(601))
   {
     dir = (dir == LEFT ? RIGHT : LEFT);
     sprite->set_action(dir == LEFT ? "left" : "right");
@@ -86,6 +86,8 @@ MrIceBlock::active_update(float elapsed_time)
 void
 MrIceBlock::collision_solid(const CollisionHit& hit)
 {
+  update_on_ground_flag(hit);
+
   if(hit.top || hit.bottom) { // floor or roof
     physic.set_velocity_y(0);
     return;
@@ -96,11 +98,13 @@ MrIceBlock::collision_solid(const CollisionHit& hit)
     case ICESTATE_NORMAL:
       if(hit.right && dir == RIGHT) {
         dir = LEFT;
+        sprite->set_action(dir == LEFT ? "left" : "right");
+        physic.set_velocity_x(-physic.get_velocity_x());       
       } else if(hit.left && dir == LEFT) {
         dir = RIGHT;
+        sprite->set_action(dir == LEFT ? "left" : "right");
+        physic.set_velocity_x(-physic.get_velocity_x());       
       }
-      sprite->set_action(dir == LEFT ? "left" : "right");
-      physic.set_velocity_x(-physic.get_velocity_x());       
       break;
     case ICESTATE_KICKED: {
 #if 0
index 0e7970b..ed0d6d4 100644 (file)
@@ -82,7 +82,7 @@ MrTree::active_update(float elapsed_time)
     activate();
   }
 
-  if (might_fall() && !recently_changed_direction )
+  if (on_ground() && might_fall() && !recently_changed_direction )
   {
     recently_changed_direction = true;
     dir = (dir == LEFT ? RIGHT : LEFT);
@@ -177,6 +177,8 @@ MrTree::collision_squished(Player& player)
 void
 MrTree::collision_solid(const CollisionHit& hit)
 {
+  update_on_ground_flag(hit);
+
   if(hit.top || hit.bottom) {
     physic.set_velocity_y(0);
   } else {
index bc00a4f..0de7bfa 100644 (file)
@@ -108,12 +108,12 @@ Snail::active_update(float elapsed_time)
   switch (state) {
 
     case STATE_NORMAL:
-      if (might_fall(601)) {
+      if (on_ground() && might_fall(601)) {
         if( recently_changed_direction ) break;
         recently_changed_direction = true;
-           dir = (dir == LEFT ? RIGHT : LEFT);
-           sprite->set_action(dir == LEFT ? "left" : "right");
-           physic.set_velocity_x(-physic.get_velocity_x());
+       dir = (dir == LEFT ? RIGHT : LEFT);
+       sprite->set_action(dir == LEFT ? "left" : "right");
+       physic.set_velocity_x(-physic.get_velocity_x());
       }
       break;
 
@@ -146,6 +146,8 @@ Snail::active_update(float elapsed_time)
 void
 Snail::collision_solid(const CollisionHit& hit)
 {
+  update_on_ground_flag(hit);
+
   if(hit.top || hit.bottom) { // floor or roof
     physic.set_velocity_y(0);
 
index befbd05..44ef749 100644 (file)
@@ -51,7 +51,7 @@ Spiky::active_update(float elapsed_time)
 {
   BadGuy::active_update(elapsed_time);
 
-  if (might_fall(601))
+  if (on_ground() && might_fall(601))
   {
     dir = (dir == LEFT ? RIGHT : LEFT);
     sprite->set_action(dir == LEFT ? "left" : "right");
@@ -62,6 +62,8 @@ Spiky::active_update(float elapsed_time)
 void
 Spiky::collision_solid(const CollisionHit& hit)
 {
+  update_on_ground_flag(hit);
+
   if(hit.top || hit.bottom) { // hit floor or roof?
     physic.set_velocity_y(0);
   } else { // hit right or left
index 2ee60f1..2f1327d 100644 (file)
@@ -90,7 +90,7 @@ Totem::active_update(float elapsed_time)
   BadGuy::active_update(elapsed_time);
 
   if (!carried_by) {
-    if (might_fall())
+    if (on_ground() && might_fall())
     {
       dir = (dir == LEFT ? RIGHT : LEFT);
       activate();
@@ -154,6 +154,8 @@ Totem::collision_squished(Player& player)
 void
 Totem::collision_solid(const CollisionHit& hit)
 {
+  update_on_ground_flag(hit);
+
   // if we are being carried around, pass event to bottom of stack and ignore it
   if (carried_by) {
     carried_by->collision_solid(hit);