expressed my opinion on code layout..
[supertux.git] / src / object / player.cpp
index 0cc997c..02cfc13 100644 (file)
@@ -94,6 +94,12 @@ namespace {
   /** instant velocity when tux starts to walk */
   static const float WALK_SPEED = 100;
 
+  /** multiplied by WALK_ACCELERATION to give friction */
+  static const float NORMAL_FRICTION_MULTIPLIER = 1.5f;
+  /** multiplied by WALK_ACCELERATION to give friction */
+  static const float ICE_FRICTION_MULTIPLIER = 0.1f;
+  static const float ICE_ACCELERATION_MULTIPLIER = 0.25f;
+
   /** time of the kick (kicking mriceblock) animation */
   static const float KICK_TIME = .3f;
   /** time of tux cheering (currently unused) */
@@ -105,6 +111,8 @@ namespace {
       the apex of the jump is reached */
   static const float JUMP_EARLY_APEX_FACTOR = 3.0;
 
+  static const float JUMP_GRACE_TIME = 0.25f; /**< time before hitting the ground that the jump button may be pressed (and still trigger a jump) */
+
   bool no_water = true;
 }
 
@@ -169,6 +177,8 @@ Player::init()
   backflip_direction = 0;
   visible = true;
   swimming = false;
+  on_ice = false;
+  ice_this_frame = false;
   speedlimit = 0; //no special limit
 
   on_ground_flag = false;
@@ -348,7 +358,11 @@ Player::update(float elapsed_time)
     grabbed_object = NULL;
   }
 
+  if(!ice_this_frame && on_ground())
+    on_ice = false;
+
   on_ground_flag = false;
+  ice_this_frame = false;
 
   // when invincible, spawn particles
   if (invincible_timer.started() && !dying)
@@ -400,10 +414,13 @@ Player::apply_friction()
   if ((on_ground()) && (fabs(physic.get_velocity_x()) < WALK_SPEED)) {
     physic.set_velocity_x(0);
     physic.set_acceleration_x(0);
-  } else if(physic.get_velocity_x() < 0) {
-    physic.set_acceleration_x(WALK_ACCELERATION_X * 1.5);
-    } else if(physic.get_velocity_x() > 0) {
-    physic.set_acceleration_x(WALK_ACCELERATION_X * -1.5);
+  } else {
+    float friction = WALK_ACCELERATION_X * (on_ice ? ICE_FRICTION_MULTIPLIER : NORMAL_FRICTION_MULTIPLIER);
+    if(physic.get_velocity_x() < 0) {
+      physic.set_acceleration_x(friction);
+    } else /*if(physic.get_velocity_x() > 0)*/ {
+      physic.set_acceleration_x(-friction);
+    }
   }
 }
 
@@ -488,6 +505,10 @@ Player::handle_horizontal_input()
     }
   }
 
+  if(on_ice) {
+    ax *= ICE_ACCELERATION_MULTIPLIER;
+  }
+
   physic.set_velocity(vx, vy);
   physic.set_acceleration(ax, ay);
 
@@ -608,7 +629,9 @@ void
 Player::handle_vertical_input()
 {
   // Press jump key
-  if(controller->pressed(Controller::JUMP) && (can_jump)) {
+  if(controller->pressed(Controller::JUMP)) jump_button_timer.start(JUMP_GRACE_TIME);
+  if(controller->hold(Controller::JUMP) && jump_button_timer.started() && can_jump) {
+    jump_button_timer.stop();
     if (duck) {
       // when running, only jump a little bit; else do a backflip
       if ((physic.get_velocity_x() != 0) || (controller->hold(Controller::LEFT)) || (controller->hold(Controller::RIGHT))) do_jump(-300); else do_backflip();
@@ -696,7 +719,7 @@ Player::handle_input()
   if (!backflipping) handle_horizontal_input();
 
   /* Jump/jumping? */
-  if (on_ground() && !controller->hold(Controller::JUMP))
+  if (on_ground())
     can_jump = true;
 
   /* Handle vertical movement: */
@@ -1067,6 +1090,11 @@ Player::collision_tile(uint32_t tile_attributes)
     }
   }
 #endif
+
+  if(tile_attributes & (Tile::ICE | Tile::SOLID)) {
+    ice_this_frame = true;
+    on_ice = true;
+  }
 }
 
 void