Game no longer needs to pause while Tux grows /
authorChristoph Sommer <mail@christoph-sommer.de>
Sun, 18 Jun 2006 14:36:11 +0000 (14:36 +0000)
committerChristoph Sommer <mail@christoph-sommer.de>
Sun, 18 Jun 2006 14:36:11 +0000 (14:36 +0000)
When Tux ducks and gets stuck under a ledge, he'll get hurt to shrink and be set free again (test at levels/test/glitches.stl)

SVN-Revision: 3673

src/game_session.cpp
src/moving_object.hpp
src/object/player.cpp
src/object/player.hpp
src/sector.hpp

index b089677..daac30f 100644 (file)
@@ -474,11 +474,9 @@ GameSession::update(float elapsed_time)
     if (end_sequence == ENDSEQUENCE_RUNNING) {
       currentsector->update(elapsed_time/2);
     } else if(end_sequence == NO_ENDSEQUENCE) {
-      if(!currentsector->player->growing_timer.started()) {
-       play_time += elapsed_time; //TODO: make sure we don't count cutscene time
-        level->stats.time = play_time;
-        currentsector->update(elapsed_time);
-      }
+      play_time += elapsed_time; //TODO: make sure we don't count cutscene time
+      level->stats.time = play_time;
+      currentsector->update(elapsed_time);
     } 
   }
 
index 63950cc..cba449c 100644 (file)
@@ -112,9 +112,21 @@ public:
    */
   virtual void set_pos(const Vector& pos)
   {
+    dest.move(pos-get_pos());
     bbox.set_pos(pos);
   }
 
+  /**
+   * sets the moving object's bbox to a specific size. Be careful when
+   * using this function. There are no collision detection checks performed
+   * here so bad things could happen.
+   */
+  virtual void set_size(float w, float h)
+  {
+    dest.set_size(w, h);
+    bbox.set_size(w, h);
+  }
+
   CollisionGroup get_group() const
   {
     return group;
index 5fb722e..39394e9 100644 (file)
@@ -64,6 +64,8 @@ static const float WALK_SPEED = 100;
 
 static const float KICK_TIME = .3;
 
+static const float UNDUCK_HURT_TIME = 0.25; /**< if Tux cannot unduck for this long, he will get hurt */
+
 // growing animation
 Surface* growingtux_left[GROWING_FRAMES];
 Surface* growingtux_right[GROWING_FRAMES];
@@ -131,7 +133,6 @@ Player::init()
     bbox.set_size(31.8, 62.8);
   else
     bbox.set_size(31.8, 30.8);
-  adjust_height = 0;
 
   dir = RIGHT;
   old_dir = dir;
@@ -176,6 +177,20 @@ Player::set_controller(Controller* controller)
   this->controller = controller;
 }
 
+bool
+Player::adjust_height(float new_height)
+{
+  Rect bbox2 = bbox;
+  bbox2.move(Vector(0, bbox.get_height() - new_height));
+  bbox2.set_height(new_height);
+  if (!Sector::current()->is_free_space(bbox2)) return false;
+  // adjust bbox accordingly
+  // note that we use members of moving_object for this, so we can run this during CD, too
+  set_pos(bbox2.p1);
+  set_size(bbox2.get_width(), bbox2.get_height());
+  return true;
+}
+
 void
 Player::update(float elapsed_time)
 {
@@ -184,12 +199,6 @@ Player::update(float elapsed_time)
     return;
   }
 
-  if(adjust_height != 0) {
-    bbox.move(Vector(0, bbox.get_height() - adjust_height));
-    bbox.set_height(adjust_height);
-    adjust_height = 0;
-  }
-
   if(!dying && !deactivated)
     handle_input();
 
@@ -518,23 +527,26 @@ Player::handle_input()
   /* Duck! */
   if (controller->hold(Controller::DOWN) && is_big() && !duck 
       && physic.get_velocity_y() == 0 && on_ground()) {
-    duck = true;
-    bbox.move(Vector(0, 32));
-    bbox.set_height(31.8);
-  } else if(!controller->hold(Controller::DOWN) && is_big() && duck) {
-    // if we have some velocity left then check if there is space for
-    // unducking
-    bbox.move(Vector(0, -32));
-    bbox.set_height(63.8);
-    if(Sector::current()->is_free_space(bbox) || (
-        physic.get_velocity_x() > -.01 && physic.get_velocity_x() < .01
-        && physic.get_velocity_y() > -.01 && physic.get_velocity_y() < .01))
-    {
+    if (adjust_height(31.8)) {
+      duck = true;
+      unduck_hurt_timer.stop();
+    } else {
+      // FIXME: what now?
+    }
+  }
+  /* Unduck! */
+  else if(!controller->hold(Controller::DOWN) && is_big() && duck) {
+    if (adjust_height(63.8)) {
       duck = false;
+      unduck_hurt_timer.stop();
     } else {
-      // undo the ducking changes
-      bbox.move(Vector(0, 32));
-      bbox.set_height(31.8); 
+      // if timer is not already running, start it.
+      if (unduck_hurt_timer.get_period() == 0) {
+        unduck_hurt_timer.start(UNDUCK_HURT_TIME);
+      } 
+      else if (unduck_hurt_timer.check()) {
+        kill(false);
+      }
     }
   }
 }
@@ -599,7 +611,7 @@ void
 Player::set_bonus(BonusType type, bool animate)
 {
   if(player_status->bonus == NO_BONUS) {
-    adjust_height = 62.8;
+    if (!adjust_height(62.8)) return;
     if(animate)
       growing_timer.start(GROWING_TIME);
   }
@@ -740,13 +752,14 @@ Player::draw(DrawingContext& context)
   /* Draw Tux */
   if(dying) {
     smalltux_gameover->draw(context, get_pos(), LAYER_FLOATINGOBJECTS + 1);
-  } else if(growing_timer.get_timeleft() > 0) {
+  } 
+  else if ((growing_timer.get_timeleft() > 0) && (!duck)) {
       if (dir == RIGHT) {
         context.draw_surface(growingtux_right[int((growing_timer.get_timegone() *
-                 GROWING_FRAMES) / GROWING_TIME)], get_pos() - Vector(0, 32), layer);
+                 GROWING_FRAMES) / GROWING_TIME)], get_pos(), layer);
       } else {
         context.draw_surface(growingtux_left[int((growing_timer.get_timegone() *
-                GROWING_FRAMES) / GROWING_TIME)], get_pos() - Vector(0, 32), layer);
+                GROWING_FRAMES) / GROWING_TIME)], get_pos(), layer);
       }
     }
   else if (safe_timer.started() && size_t(game_time*40)%2)
@@ -913,7 +926,7 @@ Player::kill(bool completely)
     } else {
       //growing_timer.start(GROWING_TIME);
       safe_timer.start(TUX_SAFE_TIME /* + GROWING_TIME */);
-      adjust_height = 30.8;
+      adjust_height(30.8);
       duck = false;
       set_bonus(NO_BONUS);
     }
index c212822..d4645a1 100644 (file)
@@ -44,7 +44,7 @@ class Portable;
 static const float TUX_SAFE_TIME = 1.8;
 static const float TUX_INVINCIBLE_TIME = 10.0;
 static const float TUX_INVINCIBLE_TIME_WARNING = 2.0;
-static const float GROWING_TIME = 1.0;
+static const float GROWING_TIME = 0.35;
 static const int GROWING_FRAMES = 7;
 
 class Camera;
@@ -199,6 +199,12 @@ public:
    */
   bool get_ghost_mode() { return ghost_mode; }
 
+  /**
+   * Changes height of bounding box.
+   * Returns true if successful, false otherwise
+   */
+  bool adjust_height(float new_height);
+
 private:
   void handle_input();
   void handle_input_ghost(); /**< input handling while in ghost mode */
@@ -215,8 +221,6 @@ private:
 
   bool visible;
 
-  float adjust_height;
-
   Portable* grabbed_object;
 
   Sprite* smalltux_gameover;
@@ -225,6 +229,8 @@ private:
   Vector floor_normal;
 
   bool ghost_mode; /**< indicates if Tux should float around and through solid objects */
+
+  Timer unduck_hurt_timer; /**< if Tux wants to stand up again after ducking and cannot, this timer is started */
 };
 
 #endif /*SUPERTUX_PLAYER_H*/
index ab96230..b2ee219 100644 (file)
@@ -129,7 +129,8 @@ public:
   void collision_tilemap(const Rect& dest, const Vector& movement, CollisionHit& hit) const;
 
   /** Checks if at the specified rectangle are gameobjects with STATIC flag set
-   * (or solid tiles from the tilemap)
+   * (or solid tiles from the tilemap).
+   * This does not(!) include badguys or players.
    */
   bool is_free_space(const Rect& rect) const;