Bug 471: Fix upward release of ice block, and grabbing cleanups.
authorFlorian Forster <supertux@octo.it>
Sat, 30 Jan 2010 09:36:44 +0000 (09:36 +0000)
committerFlorian Forster <supertux@octo.it>
Sat, 30 Jan 2010 09:36:44 +0000 (09:36 +0000)
Resolves #471. Thanks to Matt McCutchen for this patch.

SVN-Revision: 6285

src/badguy/mriceblock.cpp
src/badguy/mriceblock.hpp
src/object/player.cpp
src/object/player.hpp

index eed83fe..f4cacb5 100644 (file)
@@ -134,10 +134,6 @@ MrIceBlock::collision(GameObject& object, const CollisionHit& hit)
 HitResponse
 MrIceBlock::collision_player(Player& player, const CollisionHit& hit)
 {
-  if(dir == UP) {
-    return FORCE_MOVE;
-  }
-
   // handle kicks from left or right side
   if(ice_state == ICESTATE_FLAT && get_state() == STATE_ACTIVE) {
     if(hit.left) {
@@ -228,7 +224,7 @@ MrIceBlock::collision_squished(GameObject& object)
 }
 
 void
-MrIceBlock::set_state(IceState state)
+MrIceBlock::set_state(IceState state, bool up)
 {
   if(ice_state == state)
     return;
@@ -238,16 +234,14 @@ MrIceBlock::set_state(IceState state)
       WalkingBadguy::initialize();
       break;
     case ICESTATE_FLAT:
-      if(dir == UP) {
+      if(up) {
         physic.set_velocity_y(-KICKSPEED);
-        bbox.set_size(34, 31.8f);
       } else {
         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");
       }
+      sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
       flat_timer.start(4);
       break;
     case ICESTATE_KICKED:
@@ -280,8 +274,12 @@ MrIceBlock::grab(MovingObject&, const Vector& pos, Direction dir)
 void
 MrIceBlock::ungrab(MovingObject& , Direction dir)
 {
-  this->dir = dir;
-  set_state(dir == UP ? ICESTATE_FLAT : ICESTATE_KICKED);
+  if(dir == UP) {
+    set_state(ICESTATE_FLAT, true);
+  } else {
+    this->dir = dir;
+    set_state(ICESTATE_KICKED);
+  }
   set_colgroup_active(COLGROUP_MOVING);
 }
 
index 1f61c18..c08870b 100644 (file)
@@ -51,7 +51,7 @@ protected:
 
 protected:
   bool collision_squished(GameObject& object);
-  void set_state(IceState state);
+  void set_state(IceState state, bool up = false);
 
 private:
   IceState ice_state;
index 28a607e..77ef593 100644 (file)
@@ -375,9 +375,7 @@ Player::update(float elapsed_time)
   movement = physic.get_movement(elapsed_time);
 
   if(grabbed_object != NULL && !dying) {
-    Vector pos = get_pos() +
-      Vector(dir == LEFT ? -16 : 16, get_bbox().get_height()*0.66666 - 32);
-    grabbed_object->grab(*this, pos, dir);
+    position_grabbed_object();
   }
 
   if(grabbed_object != NULL && dying){
@@ -769,29 +767,54 @@ Player::handle_input()
   try_grab();
 
   if(!controller->hold(Controller::ACTION) && grabbed_object) {
-    // move the grabbed object a bit away from tux
-    Vector pos = get_pos() +
-      Vector(dir == LEFT ? -bbox.get_width()-1 : bbox.get_width()+1,
-             bbox.get_height()*0.66666 - 32);
-    Rectf dest(pos, pos + Vector(32, 32));
-    if(Sector::current()->is_free_of_movingstatics(dest)) {
-      MovingObject* moving_object = dynamic_cast<MovingObject*> (grabbed_object);
-      if(moving_object) {
-        moving_object->set_pos(pos);
+    MovingObject* moving_object = dynamic_cast<MovingObject*> (grabbed_object);
+    if(moving_object) {
+      // move the grabbed object a bit away from tux
+      Rectf grabbed_bbox = moving_object->get_bbox();
+      Rectf dest;
+      dest.p2.y = bbox.get_top() + bbox.get_height()*0.66666;
+      dest.p1.y = dest.p2.y - grabbed_bbox.get_height();
+      if(dir == LEFT) {
+        dest.p2.x = bbox.get_left() - 1;
+        dest.p1.x = dest.p2.x - grabbed_bbox.get_width();
       } else {
-        log_debug << "Non MovingObject grabbed?!?" << std::endl;
+        dest.p1.x = bbox.get_right() + 1;
+        dest.p2.x = dest.p1.x + grabbed_bbox.get_width();
       }
-      if(controller->hold(Controller::UP)) {
-        grabbed_object->ungrab(*this, UP);
-      } else {
-        grabbed_object->ungrab(*this, dir);
+      if(Sector::current()->is_free_of_movingstatics(dest)) {
+        moving_object->set_pos(dest.p1);
+        if(controller->hold(Controller::UP)) {
+          grabbed_object->ungrab(*this, UP);
+        } else {
+          grabbed_object->ungrab(*this, dir);
+        }
+        grabbed_object = NULL;
       }
-      grabbed_object = NULL;
+    } else {
+      log_debug << "Non MovingObject grabbed?!?" << std::endl;
     }
   }
 }
 
 void
+Player::position_grabbed_object()
+{
+  MovingObject* moving_object = dynamic_cast<MovingObject*>(grabbed_object);
+  assert(moving_object);
+
+  // Position where we will hold the lower-inner corner
+  Vector pos(get_bbox().get_left() + get_bbox().get_width()/2,
+      get_bbox().get_top() + get_bbox().get_height()*0.66666);
+
+  // Adjust to find the grabbed object's upper-left corner
+  if (dir == LEFT)
+    pos.x -= moving_object->get_bbox().get_width();
+  pos.y -= moving_object->get_bbox().get_height();
+
+  grabbed_object->grab(*this, pos, dir);
+}
+
+void
 Player::try_grab()
 {
   if(controller->hold(Controller::ACTION) && !grabbed_object
@@ -823,7 +846,7 @@ Player::try_grab()
       if(moving_object->get_bbox().contains(pos)) {
         if (climbing) stop_climbing(*climbing);
         grabbed_object = portable;
-        grabbed_object->grab(*this, get_pos(), dir);
+        position_grabbed_object();
         break;
       }
     }
index f30e454..4d63ef9 100644 (file)
@@ -303,6 +303,7 @@ public:
   SurfacePtr airarrow; /**< arrow indicating Tux' position when he's above the camera */
 
   Vector floor_normal;
+  void position_grabbed_object();
   void try_grab();
 
   bool ghost_mode; /**< indicates if Tux should float around and through solid objects */