// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <config.h>
-#include <typeinfo>
-#include <cmath>
-#include <iostream>
-#include <cassert>
+#include "player.hpp"
-#include "gettext.hpp"
-#include "sprite/sprite_manager.hpp"
#include "audio/sound_manager.hpp"
-#include "player.hpp"
-#include "tile.hpp"
-#include "sprite/sprite.hpp"
-#include "sector.hpp"
-#include "resources.hpp"
-#include "statistics.hpp"
+#include "badguy/badguy.hpp"
+#include "control/codecontroller.hpp"
+#include "control/joystickkeyboardcontroller.hpp"
+#include "display_effect.hpp"
+#include "log.hpp"
+#include "falling_coin.hpp"
#include "game_session.hpp"
-#include "object/tilemap.hpp"
+#include "gettext.hpp"
+#include "main.hpp"
+#include "object/bullet.hpp"
#include "object/camera.hpp"
-#include "object/particles.hpp"
#include "object/portable.hpp"
-#include "object/bullet.hpp"
-#include "trigger/trigger_base.hpp"
-#include "control/joystickkeyboardcontroller.hpp"
-#include "scripting/squirrel_util.hpp"
-#include "main.hpp"
-#include "platform.hpp"
-#include "badguy/badguy.hpp"
+#include "object/sprite_particle.hpp"
+#include "object/tilemap.hpp"
+#include "particles.hpp"
#include "player_status.hpp"
-#include "log.hpp"
-#include "falling_coin.hpp"
#include "random_generator.hpp"
-#include "object/sprite_particle.hpp"
+#include "sector.hpp"
+#include "scripting/squirrel_util.hpp"
+#include "sprite/sprite.hpp"
+#include "sprite/sprite_manager.hpp"
+#include "tile.hpp"
#include "trigger/climbable.hpp"
+#include <typeinfo>
+#include <cmath>
+#include <iostream>
+#include <cassert>
+
//#define SWIMMING
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) */
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;
}
backflip_direction = 0;
visible = true;
swimming = false;
+ on_ice = false;
+ ice_this_frame = false;
speedlimit = 0; //no special limit
on_ground_flag = false;
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)
Vector ppos = Vector(px, py);
Vector pspeed = Vector(0, 0);
Vector paccel = Vector(0, 0);
- // draw bright sparkle when there is lots of time left, dark sparkle when invincibility is about to end
- if (invincible_timer.get_timeleft() > TUX_INVINCIBLE_TIME_WARNING) {
- // make every other a longer sparkle to make trail a bit fuzzy
- if (size_t(game_time*20)%2) {
- Sector::current()->add_object(new SpriteParticle("images/objects/particles/sparkle.sprite", "small", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS+1+5));
- } else {
- Sector::current()->add_object(new SpriteParticle("images/objects/particles/sparkle.sprite", "medium", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS+1+5));
- }
- } else {
- Sector::current()->add_object(new SpriteParticle("images/objects/particles/sparkle.sprite", "dark", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS+1+5));
- }
+ Sector::current()->add_object(new SpriteParticle("images/objects/particles/sparkle.sprite",
+ // draw bright sparkle when there is lots of time left, dark sparkle when invincibility is about to end
+ (invincible_timer.get_timeleft() > TUX_INVINCIBLE_TIME_WARNING) ?
+ // make every other a longer sparkle to make trail a bit fuzzy
+ (size_t(game_time*20)%2) ? "small" : "medium"
+ :
+ "dark", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS+1+5));
}
}
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 {
+ 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(WALK_ACCELERATION_X * -1.5);
+ physic.set_acceleration_x(-friction);
+ } // no friction for physic.get_velocity_x() == 0
}
}
}
}
+ if(on_ice) {
+ ax *= ICE_ACCELERATION_MULTIPLIER;
+ }
+
physic.set_velocity(vx, vy);
physic.set_acceleration(ax, ay);
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();
}
/* Peeking */
- if( controller->released( Controller::PEEK_LEFT ) ) {
- peekingX = AUTO;
- }
- if( controller->released( Controller::PEEK_RIGHT ) ) {
+ if( controller->released( Controller::PEEK_LEFT ) || controller->released( Controller::PEEK_RIGHT ) ) {
peekingX = AUTO;
}
- if( controller->released( Controller::PEEK_UP ) ) {
- peekingY = AUTO;
- }
- if( controller->released( Controller::PEEK_DOWN ) ) {
+ if( controller->released( Controller::PEEK_UP ) || controller->released( Controller::PEEK_DOWN ) ) {
peekingY = AUTO;
}
if( controller->pressed( Controller::PEEK_LEFT ) ) {
if (!backflipping) handle_horizontal_input();
/* Jump/jumping? */
- if (on_ground() && !controller->hold(Controller::JUMP))
+ if (on_ground())
can_jump = true;
/* Handle vertical movement: */
}
}
#endif
+
+ if(tile_attributes & Tile::ICE) {
+ ice_this_frame = true;
+ on_ice = true;
+ }
}
void
dying_timer.start(3.0);
set_group(COLGROUP_DISABLED);
- DisplayEffect* effect = new DisplayEffect();
- effect->fade_out(3.0);
- Sector::current()->add_object(effect);
+ Sector::current()->effect->fade_out(3.0);
sound_manager->stop_music(3.0);
}
}
void
Player::check_bounds(Camera* camera)
{
- /* Keep tux in bounds: */
+ /* Keep tux in sector bounds: */
if (get_pos().x < 0) {
- // Lock Tux to the size of the level, so that he doesn't fall of
- // on the left side
+ // Lock Tux to the size of the level, so that he doesn't fall off
+ // the left side
set_pos(Vector(0, get_pos().y));
}
+ if (get_bbox().get_right() > Sector::current()->get_width()) {
+ // Lock Tux to the size of the level, so that he doesn't fall off
+ // the right side
+ set_pos(Vector(Sector::current()->get_width() - get_bbox().get_width(), get_pos().y));
+ }
+
/* fallen out of the level? */
if ((get_pos().y > Sector::current()->get_height()) && (!ghost_mode)) {
kill(true);