more work on MrIceBlock, you can carry him around and kick him again
authorMatthias Braun <matze@braunis.de>
Mon, 9 Jan 2006 22:46:54 +0000 (22:46 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 9 Jan 2006 22:46:54 +0000 (22:46 +0000)
SVN-Revision: 2977

src/badguy/mriceblock.cpp
src/badguy/mriceblock.hpp
src/direction.hpp
src/game_object.hpp
src/object/player.cpp
src/object/player.hpp
src/object/portable.hpp
src/object/rock.cpp
src/object/rock.hpp

index 0525848..7da4bf3 100644 (file)
@@ -62,7 +62,10 @@ MrIceBlock::write(lisp::Writer& writer)
 void
 MrIceBlock::activate()
 {
-  if (set_direction) {dir = initial_direction;}
+  if (set_direction) {
+    dir = initial_direction;
+  }
+
   physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
   sprite->set_action(dir == LEFT ? "left" : "right");
 }
@@ -70,11 +73,13 @@ MrIceBlock::activate()
 void
 MrIceBlock::active_update(float elapsed_time)
 {
+  if(ice_state == ICESTATE_GRABBED)
+    return;
+
   if(ice_state == ICESTATE_FLAT && flat_timer.check()) {
-    ice_state = ICESTATE_NORMAL;
-    physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
-    sprite->set_action(dir == LEFT ? "left" : "right");
+    set_state(ICESTATE_NORMAL);
   }
+  
   BadGuy::active_update(elapsed_time);
 }
 
@@ -111,12 +116,48 @@ MrIceBlock::collision_solid(GameObject& object, const CollisionHit& hit)
     case ICESTATE_FLAT:
       physic.set_velocity_x(0);
       break;
+    case ICESTATE_GRABBED:
+      return FORCE_MOVE;
   }
 
   return CONTINUE;
 }
 
 HitResponse
+MrIceBlock::collision(GameObject& object, const CollisionHit& hit)
+{
+  if(ice_state == ICESTATE_GRABBED)
+    return FORCE_MOVE;
+
+  return BadGuy::collision(object, hit);
+}
+
+HitResponse
+MrIceBlock::collision_player(Player& player, const CollisionHit& hit)
+{
+  if(ice_state == ICESTATE_GRABBED)
+    return FORCE_MOVE;
+
+  // handle kicks from left or right side
+  if(ice_state == ICESTATE_FLAT && get_state() == STATE_ACTIVE) {
+    // hit from left side
+    if(hit.normal.x > 0.7) {
+      dir = RIGHT;
+      player.kick();
+      set_state(ICESTATE_KICKED);
+      return FORCE_MOVE;
+    } else if(hit.normal.x < -0.7) {
+      dir = LEFT;
+      player.kick();
+      set_state(ICESTATE_KICKED);
+      return FORCE_MOVE;
+    }
+  }
+  
+  return BadGuy::collision_player(player, hit);
+}
+
+HitResponse
 MrIceBlock::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
 {
   switch(ice_state) {
@@ -151,32 +192,86 @@ MrIceBlock::collision_squished(Player& player)
         return true;
       }
 
-      // flatten
+      set_state(ICESTATE_FLAT);
+      break;
+    case ICESTATE_FLAT:
+      if(player.get_pos().x < get_pos().x) {
+        dir = RIGHT;
+      } else {
+        dir = LEFT;
+      }
+      set_state(ICESTATE_KICKED);
+      break;
+    case ICESTATE_GRABBED:
+      assert(false);
+      break;
+  }
+
+  player.bounce(*this);
+  return true;
+}
+
+void
+MrIceBlock::set_state(IceState state)
+{
+  if(ice_state == state)
+    return;
+  
+  if(state == ICESTATE_FLAT)
+    flags |= FLAG_PORTABLE;
+  else
+    flags &= ~FLAG_PORTABLE;
+
+  if(ice_state == ICESTATE_KICKED) {
+    bbox.set_size(31.8, 31.8);
+  }
+
+  switch(state) {
+    case ICESTATE_NORMAL:
+      physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
+      sprite->set_action(dir == LEFT ? "left" : "right");
+      break;
+    case ICESTATE_FLAT:
       sound_manager->play("sounds/stomp.wav", get_pos());
       physic.set_velocity_x(0);
       physic.set_velocity_y(0); 
       
       sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
       flat_timer.start(4);
-      ice_state = ICESTATE_FLAT;
       break;
-    case ICESTATE_FLAT:
-      // kick
+    case ICESTATE_KICKED:
       sound_manager->play("sounds/kick.wav", get_pos());
 
-      if(player.get_pos().x < get_pos().x) {
-        dir = RIGHT;
-      } else {
-        dir = LEFT;
-      }
       physic.set_velocity_x(dir == LEFT ? -KICKSPEED : KICKSPEED);
       sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
-      ice_state = ICESTATE_KICKED;
+      // we should slide above 1 block holes now...
+      bbox.set_size(32.5, 31.8);
+      break;
+    case ICESTATE_GRABBED:
+      flat_timer.stop();
       break;
+    default:
+      assert(false);
   }
+  ice_state = state;
+}
 
-  player.bounce(*this);
-  return true;
+void
+MrIceBlock::grab(MovingObject&, const Vector& pos, Direction dir)
+{
+  movement = pos - get_pos();
+  this->dir = dir;
+  sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
+  set_state(ICESTATE_GRABBED);
+  set_group(COLGROUP_DISABLED);
+}
+
+void
+MrIceBlock::ungrab(MovingObject& , Direction dir)
+{
+  this->dir = dir;
+  set_state(ICESTATE_KICKED);
+  set_group(COLGROUP_MOVING);
 }
 
 IMPLEMENT_FACTORY(MrIceBlock, "mriceblock")
index 4031e0d..bd0ff53 100644 (file)
@@ -22,8 +22,9 @@
 #define __MRICEBLOCK_H__
 
 #include "badguy.hpp"
+#include "object/portable.hpp"
 
-class MrIceBlock : public BadGuy
+class MrIceBlock : public BadGuy, public Portable
 {
 public:
   MrIceBlock(const lisp::Lisp& reader);
@@ -31,10 +32,15 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
+  HitResponse collision(GameObject& object, const CollisionHit& hit);
   HitResponse collision_solid(GameObject& object, const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
+  HitResponse collision_player(Player& player, const CollisionHit& hit);
 
   void active_update(float elapsed_time);
+  
+  void grab(MovingObject& object, const Vector& pos, Direction dir);
+  void ungrab(MovingObject& object, Direction dir);
 
 protected:
   bool collision_squished(Player& player);
@@ -43,13 +49,17 @@ private:
   enum IceState {
     ICESTATE_NORMAL,
     ICESTATE_FLAT,
+    ICESTATE_GRABBED,
     ICESTATE_KICKED
   };
+
+  void set_state(IceState state);
   IceState ice_state;
   Timer flat_timer;
   int squishcount;
   bool set_direction;
-  Direction initial_direction;  
+  Direction initial_direction;
 };
 
 #endif
index 5ecc417..ac32a21 100644 (file)
@@ -23,5 +23,4 @@
 
 enum Direction { LEFT = 0, RIGHT = 1 };
 
-#endif /*SUPERTUX_DEFINES_H*/
-
+#endif
index 6e0c4ee..a1734ab 100644 (file)
@@ -78,7 +78,9 @@ public:
   // flags
   enum {
     /// the tile so you can stand on it
-    FLAG_SOLID       = 0x0001,
+    FLAG_SOLID       = (1 << 0),
+    /// the object can be carried around (inherits from Portable)
+    FLAG_PORTABLE    = (1 << 1)
   };                     
 
   int get_flags() const
index 043a770..884059f 100644 (file)
@@ -57,6 +57,8 @@ static const float MAX_WALK_XM = 230;
 static const float MAX_RUN_XM = 320;
 static const float WALK_SPEED = 100;
 
+static const float KICK_TIME = .3;
+
 // growing animation
 Surface* growingtux_left[GROWING_FRAMES];
 Surface* growingtux_right[GROWING_FRAMES];
@@ -177,6 +179,7 @@ Player::update(float elapsed_time)
         std::cout << "Non MovingObjetc grabbed?!?\n";
 #endif
       }
+      grabbed_object->ungrab(*this, dir);
       grabbed_object = 0;
     }
   }
@@ -201,7 +204,7 @@ Player::update(float elapsed_time)
     Vector pos = get_pos() + 
       Vector(dir == LEFT ? -16 : 16,
              bbox.get_height()*0.66666 - 32);
-    grabbed_object->grab(*this, pos);
+    grabbed_object->grab(*this, pos, dir);
   }
 }
 
@@ -520,6 +523,12 @@ Player::set_bonus(BonusType type, bool animate)
 }
 
 void
+Player::kick()
+{
+  kick_timer.start(KICK_TIME);
+}
+
+void
 Player::draw(DrawingContext& context)
 {
   TuxBodyParts* tux_body;
@@ -682,11 +691,13 @@ Player::collision(GameObject& other, const CollisionHit& hit)
     return FORCE_MOVE;
   }
 
-  Portable* portable = dynamic_cast<Portable*> (&other);
-  if(portable && grabbed_object == 0 && controller->hold(Controller::ACTION)
-     && fabsf(hit.normal.x) > .9) {
-    grabbed_object = portable;
-    return CONTINUE;
+  if(other.get_flags() & FLAG_PORTABLE) {
+    Portable* portable = dynamic_cast<Portable*> (&other);
+    if(portable && grabbed_object == 0 && controller->hold(Controller::ACTION)
+        && fabsf(hit.normal.x) > .9) {
+      grabbed_object = portable;
+      return CONTINUE;
+    }
   }
  
   if(other.get_flags() & FLAG_SOLID) {
index 253364d..b247186 100644 (file)
@@ -144,6 +144,8 @@ public:
   {
     return player_status;
   }
+  // set kick animation
+  void kick();
 
   void bounce(BadGuy& badguy);
 
index ae7199b..265f0a0 100644 (file)
@@ -21,6 +21,7 @@
 #define __PORTABLE_H__
 
 #include "moving_object.hpp"
+#include "direction.hpp"
 
 /**
  * An object that inherits from this object is considered "portable" and can
@@ -37,7 +38,10 @@ public:
   /**
    * called each frame when the object has been grabbed.
    */
-  virtual void grab(MovingObject& object, const Vector& pos) = 0;
+  virtual void grab(MovingObject& object, const Vector& pos, Direction dir) = 0;
+
+  virtual void ungrab(MovingObject& , Direction )
+  {}
 };
 
 #endif
index df1371c..b6ad844 100644 (file)
@@ -91,7 +91,7 @@ Rock::collision(GameObject& object, const CollisionHit& )
 }
 
 void
-Rock::grab(MovingObject& , const Vector& pos)
+Rock::grab(MovingObject& , const Vector& pos, Direction)
 {
   movement = pos - get_pos();
   grabbed = true;
index 9e48d1b..1ddce97 100644 (file)
@@ -39,7 +39,7 @@ public:
   void draw(DrawingContext& context);
   void write(lisp::Writer& writer);
     
-  void grab(MovingObject& object, const Vector& pos);
+  void grab(MovingObject& object, const Vector& pos, Direction dir);
 
 private:
   bool grabbed;