IceCrusher: Use gavitation rather than linear speed when "crushing".
authorFlorian Forster <supertux@octo.it>
Fri, 26 Feb 2010 19:16:59 +0000 (19:16 +0000)
committerFlorian Forster <supertux@octo.it>
Fri, 26 Feb 2010 19:16:59 +0000 (19:16 +0000)
Moving up is still done using a linear speed because it felt better.

SVN-Revision: 6403

data/images/creatures/icecrusher/icecrusher.sprite
src/object/icecrusher.cpp
src/object/icecrusher.hpp

index 972f5e1..0727f85 100644 (file)
@@ -5,4 +5,16 @@
   (images "iceblock.png"
   )
  )
+ (action
+  (name "crushing")
+  (hitbox 11 8 64 64)
+  (images "iceblock.png"
+  )
+ )
+ (action
+  (name "recovering")
+  (hitbox 11 8 64 64)
+  (images "iceblock.png"
+  )
+ )
 )
index aef8dd5..38e2507 100644 (file)
@@ -1,5 +1,6 @@
 //  IceCrusher - A block to stand on, which can drop down to crush the player
 //  Copyright (C) 2008 Christoph Sommer <christoph.sommer@2008.expires.deltadevelopment.de>
+//  Copyright (C) 2010 Florian Forster <supertux at octo.it>
 //
 //  This program is free software: you can redistribute it and/or modify
 //  it under the terms of the GNU General Public License as published by
 #include "supertux/sector.hpp"
 
 namespace {
-const float DROP_SPEED = 500;
-const float RECOVER_SPEED = 200;
+/* Maximum movement speed in pixels per LOGICAL_FPS */
+const float MAX_DROP_SPEED = 10.0;
+const float RECOVER_SPEED = -3.125;
+const float ACTIVATION_DISTANCE = 4.0;
 }
 
 IceCrusher::IceCrusher(const Reader& reader) :
   MovingSprite(reader, "images/creatures/icecrusher/icecrusher.sprite", LAYER_OBJECTS, COLGROUP_STATIC), 
   state(IDLE), 
   start_position(),
-  speed(Vector(0,0))
+  physic()
 {
   start_position = get_bbox().p1;
   set_state(state, true);
@@ -53,18 +56,19 @@ IceCrusher::set_state(IceCrusherState state, bool force)
   switch(state) {
     case IDLE:
       set_group(COLGROUP_STATIC);
-      speed=Vector(0,0);
+      physic.enable_gravity (false);
       sprite->set_action("idle");
       break;
     case CRUSHING:
       set_group(COLGROUP_MOVING_STATIC);
-      speed=Vector(0, DROP_SPEED);
-      sprite->set_action("idle");
+      physic.reset ();
+      physic.enable_gravity (true);
+      sprite->set_action("crushing");
       break;
     case RECOVERING:
       set_group(COLGROUP_MOVING_STATIC);
-      speed=Vector(0, -RECOVER_SPEED);
-      sprite->set_action("idle");
+      physic.enable_gravity (false);
+      sprite->set_action("recovering");
       break;
     default:
       log_debug << "IceCrusher in invalid state" << std::endl;
@@ -77,13 +81,18 @@ HitResponse
 IceCrusher::collision(GameObject& other, const CollisionHit& hit)
 {
   Player* player = dynamic_cast<Player*>(&other);
+
+  /* If the other object is the player, and the collision is at the bottom of
+   * the ice crusher, hurt the player. */
   if (player && hit.bottom) {
     if(player->is_invincible()) {
-      if (state == CRUSHING) set_state(RECOVERING);
+      if (state == CRUSHING)
+        set_state(RECOVERING);
       return ABORT_MOVE;
     }
     player->kill(false);
-    if (state == CRUSHING) set_state(RECOVERING);
+    if (state == CRUSHING)
+      set_state(RECOVERING);
     return FORCE_MOVE;
   }
   BadGuy* badguy = dynamic_cast<BadGuy*>(&other);
@@ -94,13 +103,15 @@ IceCrusher::collision(GameObject& other, const CollisionHit& hit)
 }
     
 void 
-IceCrusher::collision_solid(const CollisionHit& )
+IceCrusher::collision_solid(const CollisionHit& hit)
 {
   switch(state) {
     case IDLE:
       break;
     case CRUSHING:
-      set_state(RECOVERING);
+      if (hit.bottom) {
+        set_state(RECOVERING);
+      }
       break;
     case RECOVERING:
       break;
@@ -115,21 +126,29 @@ IceCrusher::update(float elapsed_time)
 {
   switch(state) {
     case IDLE:
-      if (found_victim()) set_state(CRUSHING);
+      movement = Vector (0, 0);
+      if (found_victim())
+        set_state(CRUSHING);
       break;
     case CRUSHING:
+      movement = physic.get_movement (elapsed_time);
+      if (movement.y > MAX_DROP_SPEED)
+        movement.y = MAX_DROP_SPEED;
       break;
     case RECOVERING:
       if (get_bbox().p1.y <= start_position.y+1) {
         set_pos(start_position);
+        movement = Vector (0, 0);
         set_state(IDLE);
       }
+      else {
+        movement = Vector (0, RECOVER_SPEED);
+      }
       break;
     default:
       log_debug << "IceCrusher in invalid state" << std::endl;
       break;
   }
-  movement = speed * elapsed_time;
 }
 
 Player*
@@ -153,12 +172,14 @@ IceCrusher::found_victim()
   Player* player = this->get_nearest_player();
   if (!player) return false;
 
-  const Rectf& pr = player->get_bbox();
-  const Rectf& br = get_bbox();
-  if ((pr.p2.x > br.p1.x) && (pr.p1.x < br.p2.x) && (pr.p1.y >= br.p2.y)) {
+  const Rectf& player_bbox = player->get_bbox();
+  const Rectf& crusher_bbox = get_bbox();
+  if ((player_bbox.p1.y >= crusher_bbox.p2.y) /* player is below crusher */
+      && (player_bbox.p2.x > (crusher_bbox.p1.x - ACTIVATION_DISTANCE))
+      && (player_bbox.p1.x < (crusher_bbox.p2.x + ACTIVATION_DISTANCE)))
     return true;
-  }
-  return false;
+  else
+    return false;
 }
 
 /* EOF */
index 0080937..2a0c5f9 100644 (file)
@@ -18,6 +18,7 @@
 #define HEADER_SUPERTUX_OBJECT_ICECRUSHER_HPP
 
 #include "object/moving_sprite.hpp"
+#include "supertux/physic.hpp"
 
 class Player;
 
@@ -34,10 +35,12 @@ public:
   virtual void collision_solid(const CollisionHit& hit);
   virtual void update(float elapsed_time);
 
+#if 0
   const Vector& get_speed() const
   {
     return speed;
   }
+#endif
 
 protected:
   enum IceCrusherState {
@@ -47,7 +50,7 @@ protected:
   };
   IceCrusherState state;
   Vector start_position;
-  Vector speed;
+  Physic physic;
 
   Player* get_nearest_player();
   bool found_victim();