X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fobject%2Fplayer.cpp;h=a6aeed78be02de5e7992c9835d26f289a679470b;hb=33b66711ec8c2f563a454f386a678eedd20a64a7;hp=2e2ea284084f768f67828fa7a6563f8967f830ab;hpb=3bdde1dc2696340bee5f52dea1d8f288700f62b9;p=supertux.git diff --git a/src/object/player.cpp b/src/object/player.cpp index 2e2ea2840..a6aeed78b 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -19,7 +19,7 @@ #include "audio/sound_manager.hpp" #include "badguy/badguy.hpp" -#include "control/joystickkeyboardcontroller.hpp" +#include "control/input_manager.hpp" #include "math/random_generator.hpp" #include "object/bullet.hpp" #include "object/camera.hpp" @@ -40,9 +40,9 @@ //#define SWIMMING namespace { -static const int TILES_FOR_BUTTJUMP = 3; static const float BUTTJUMP_MIN_VELOCITY_Y = 400.0f; static const float SHOOTING_TIME = .150f; +static const float GLIDE_TIME_PER_FLOWER = 0.5f; /** number of idle stages, including standing */ static const unsigned int IDLE_STAGE_COUNT = 5; @@ -63,7 +63,7 @@ static const std::string IDLE_STAGES[] = /** acceleration in horizontal direction when walking * (all accelerations are in pixel/s^2) */ static const float WALK_ACCELERATION_X = 300; -/** acceleration in horizontal direction when running */ +/** acceleration in horizontal direction when running */ static const float RUN_ACCELERATION_X = 400; /** acceleration when skidding */ static const float SKID_XM = 200; @@ -73,10 +73,14 @@ static const float SKID_TIME = .3f; static const float MAX_WALK_XM = 230; /** maximum run velocity (pixel/s) */ static const float MAX_RUN_XM = 320; +/** bonus run velocity addition (pixel/s) */ +static const float BONUS_RUN_XM = 80; /** maximum horizontal climb velocity */ static const float MAX_CLIMB_XM = 96; /** maximum vertical climb velocity */ static const float MAX_CLIMB_YM = 128; +/** maximum vertical glide velocity */ +static const float MAX_GLIDE_YM = 128; /** instant velocity when tux starts to walk */ static const float WALK_SPEED = 100; @@ -88,8 +92,6 @@ 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) */ -static const float CHEER_TIME = 1.0f; /** if Tux cannot unduck for this long, he will get hurt */ static const float UNDUCK_HURT_TIME = 0.25f; @@ -109,24 +111,28 @@ static const float DUCKED_TUX_HEIGHT = 31.8f; bool no_water = true; } -Player::Player(PlayerStatus* _player_status, const std::string& name) : +Player::Player(PlayerStatus* _player_status, const std::string& name_) : deactivated(), controller(), - scripting_controller(0), - player_status(_player_status), + scripting_controller(), + player_status(_player_status), duck(), dead(), dying(), + winning(), backflipping(), backflip_direction(), peekingX(), peekingY(), + glide_time(), + stone(), swimming(), speedlimit(), scripting_controller_old(0), jump_early_apex(), on_ice(), ice_this_frame(), + lightsprite(SpriteManager::current()->create("images/objects/lightmap_light/lightmap_light-tiny.sprite")), dir(), old_dir(), last_ground_y(), @@ -134,7 +140,7 @@ Player::Player(PlayerStatus* _player_status, const std::string& name) : on_ground_flag(), jumping(), can_jump(), - jump_button_timer(), + jump_button_timer(), wants_buttjump(), does_buttjump(), invincible_timer(), @@ -142,40 +148,42 @@ Player::Player(PlayerStatus* _player_status, const std::string& name) : safe_timer(), kick_timer(), shooting_timer(), + ability_timer(), + cooldown_timer(), dying_timer(), growing(), backflip_timer(), physic(), visible(), - grabbed_object(NULL), + grabbed_object(NULL), sprite(), airarrow(), floor_normal(), - ghost_mode(false), - edit_mode(false), + ghost_mode(false), + edit_mode(false), unduck_hurt_timer(), idle_timer(), idle_stage(0), climbing(0) { - this->name = name; - controller = g_jk_controller->get_main_controller(); + this->name = name_; + controller = InputManager::current()->get_controller(); scripting_controller.reset(new CodeController()); // if/when we have complete penny gfx, we can // load those instead of Tux's sprite in the // constructor - sprite = sprite_manager->create("images/creatures/tux/tux.sprite"); + sprite = SpriteManager::current()->create("images/creatures/tux/tux.sprite"); airarrow = Surface::create("images/engine/hud/airarrow.png"); idle_timer.start(IDLE_TIME[0]/1000.0f); - sound_manager->preload("sounds/bigjump.wav"); - sound_manager->preload("sounds/jump.wav"); - sound_manager->preload("sounds/hurt.wav"); - sound_manager->preload("sounds/kill.wav"); - sound_manager->preload("sounds/skid.wav"); - sound_manager->preload("sounds/flip.wav"); - sound_manager->preload("sounds/invincible_start.ogg"); - sound_manager->preload("sounds/splash.ogg"); + SoundManager::current()->preload("sounds/bigjump.wav"); + SoundManager::current()->preload("sounds/jump.wav"); + SoundManager::current()->preload("sounds/hurt.wav"); + SoundManager::current()->preload("sounds/kill.wav"); + SoundManager::current()->preload("sounds/skid.wav"); + SoundManager::current()->preload("sounds/flip.wav"); + SoundManager::current()->preload("sounds/invincible_start.ogg"); + SoundManager::current()->preload("sounds/splash.ogg"); init(); } @@ -215,10 +223,13 @@ Player::init() backflip_direction = 0; sprite->set_angle(0.0f); visible = true; + glide_time = 0; + stone = false; swimming = false; on_ice = false; ice_this_frame = false; speedlimit = 0; //no special limit + lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE)); on_ground_flag = false; grabbed_object = NULL; @@ -259,9 +270,9 @@ Player::set_speedlimit(float newlimit) } void -Player::set_controller(Controller* controller) +Player::set_controller(Controller* controller_) { - this->controller = controller; + this->controller = controller_; } void @@ -273,7 +284,7 @@ Player::set_winning() } } -void +void Player::use_scripting_controller(bool use_or_release) { if ((use_or_release == true) && (controller != scripting_controller.get())) { @@ -286,7 +297,7 @@ Player::use_scripting_controller(bool use_or_release) } } -void +void Player::do_scripting_controller(std::string control, bool pressed) { for(int i = 0; Controller::controlNames[i] != 0; ++i) { @@ -345,11 +356,11 @@ Player::update(float elapsed_time) if(!dying && !deactivated) handle_input(); -/* + /* // handle_input() calls apply_friction() when Tux is not walking, so we'll have to do this ourselves if (deactivated) - apply_friction(); -*/ + apply_friction(); + */ // extend/shrink tux collision rectangle so that we fall through/walk over 1 // tile holes @@ -400,6 +411,8 @@ Player::update(float elapsed_time) if (deactivated) do_standup(); } + if (player_status->bonus == AIR_BONUS) + glide_time = player_status->max_air_time * GLIDE_TIME_PER_FLOWER; } // calculate movement for this frame @@ -429,13 +442,15 @@ Player::update(float elapsed_time) Vector ppos = Vector(px, py); Vector pspeed = Vector(0, 0); Vector paccel = Vector(0, 0); - 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)); + Sector::current()->add_object(std::make_shared( + "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)); } } @@ -524,11 +539,11 @@ Player::handle_horizontal_input() ax = dirsign * RUN_ACCELERATION_X; } // limit speed - if(vx >= MAX_RUN_XM && dirsign > 0) { - vx = MAX_RUN_XM; + if(vx >= MAX_RUN_XM + BONUS_RUN_XM *((player_status->bonus == AIR_BONUS) ? 1 : 0) && dirsign > 0) { + vx = MAX_RUN_XM + BONUS_RUN_XM *((player_status->bonus == AIR_BONUS) ? 1 : 0); ax = 0; - } else if(vx <= -MAX_RUN_XM && dirsign < 0) { - vx = -MAX_RUN_XM; + } else if(vx <= -MAX_RUN_XM - BONUS_RUN_XM *((player_status->bonus == AIR_BONUS) ? 1 : 0) && dirsign < 0) { + vx = -MAX_RUN_XM - BONUS_RUN_XM *((player_status->bonus == AIR_BONUS) ? 1 : 0); ax = 0; } } @@ -549,10 +564,10 @@ Player::handle_horizontal_input() // let's skid! if(fabs(vx)>SKID_XM && !skidding_timer.started()) { skidding_timer.start(SKID_TIME); - sound_manager->play("sounds/skid.wav"); + SoundManager::current()->play("sounds/skid.wav"); // dust some particles Sector::current()->add_object( - new Particles( + std::make_shared( Vector(dir == RIGHT ? get_bbox().p2.x : get_bbox().p1.x, get_bbox().p2.y), dir == RIGHT ? 270+20 : 90-40, dir == RIGHT ? 270+40 : 90-20, Vector(280, -260), Vector(0, 300), 3, Color(.4f, .4f, .4f), 3, .8f, @@ -642,8 +657,8 @@ Player::do_backflip() { backflip_direction = (dir == LEFT)?(+1):(-1); backflipping = true; - do_jump(-580); - sound_manager->play("sounds/flip.wav"); + do_jump((player_status->bonus == AIR_BONUS) ? -720 : -580); + SoundManager::current()->play("sounds/flip.wav"); backflip_timer.start(TUX_BACKFLIP_TIME); } @@ -660,14 +675,14 @@ Player::do_jump(float yspeed) { // play sound if (is_big()) { - sound_manager->play("sounds/bigjump.wav"); + SoundManager::current()->play("sounds/bigjump.wav"); } else { - sound_manager->play("sounds/jump.wav"); + SoundManager::current()->play("sounds/jump.wav"); } } void -Player::early_jump_apex() +Player::early_jump_apex() { if (!jump_early_apex) { @@ -695,27 +710,52 @@ Player::handle_vertical_input() 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))) + if ((physic.get_velocity_x() != 0) || + (controller->hold(Controller::LEFT)) || + (controller->hold(Controller::RIGHT))) { do_jump(-300); } - else + else { do_backflip(); } } else { + // airflower allows for higher jumps- // jump a bit higher if we are running; else do a normal jump - if (fabs(physic.get_velocity_x()) > MAX_WALK_XM) do_jump(-580); else do_jump(-520); + if(player_status->bonus == AIR_BONUS) + do_jump((fabs(physic.get_velocity_x()) > MAX_WALK_XM) ? -620 : -580); + else + do_jump((fabs(physic.get_velocity_x()) > MAX_WALK_XM) ? -580 : -520); } - } + // airflower glide only when holding jump key + } else if (controller->hold(Controller::JUMP) && player_status->bonus == AIR_BONUS && physic.get_velocity_y() > MAX_GLIDE_YM) { + if (glide_time > 0 && !ability_timer.started()) + ability_timer.start(glide_time); + else if (ability_timer.started()) { + log_debug << ability_timer.get_timeleft() << std::endl; + // glide stops after some duration or if buttjump is initiated + if ((ability_timer.get_timeleft() <= 0.05f) || controller->hold(Controller::DOWN)) { + glide_time = 0; + ability_timer.stop(); + } else { + physic.set_velocity_y(MAX_GLIDE_YM); + physic.set_acceleration_y(0); + } + } + } + /*ability_timer.started() ? gliding = true : ability_timer.start(player_status->max_air_time);*/ + //} // Let go of jump key else if(!controller->hold(Controller::JUMP)) { if (!backflipping && jumping && physic.get_velocity_y() < 0) { jumping = false; early_jump_apex(); } + if (player_status->bonus == AIR_BONUS && ability_timer.started()){ + glide_time = ability_timer.get_timeleft(); + ability_timer.stop(); + } } if(jump_early_apex && physic.get_velocity_y() >= 0) { @@ -814,18 +854,18 @@ Player::handle_input() 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(); + 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(); + dest_.p2.x = bbox.get_left() - 1; + dest_.p1.x = dest_.p2.x - grabbed_bbox.get_width(); } else { - dest.p1.x = bbox.get_right() + 1; - dest.p2.x = dest.p1.x + grabbed_bbox.get_width(); + dest_.p1.x = bbox.get_right() + 1; + dest_.p2.x = dest_.p1.x + grabbed_bbox.get_width(); } - if(Sector::current()->is_free_of_tiles(dest, true)) { - moving_object->set_pos(dest.p1); + if(Sector::current()->is_free_of_tiles(dest_, true)) { + moving_object->set_pos(dest_.p1); if(controller->hold(Controller::UP)) { grabbed_object->ungrab(*this, UP); } else { @@ -952,6 +992,10 @@ Player::add_bonus(const std::string& bonustype) type = FIRE_BONUS; } else if(bonustype == "iceflower") { type = ICE_BONUS; + } else if(bonustype == "airflower") { + type = AIR_BONUS; + } else if(bonustype == "earthflower") { + type = EARTH_BONUS; } else if(bonustype == "none") { type = NO_BONUS; } else { @@ -973,11 +1017,7 @@ Player::add_bonus(BonusType type, bool animate) // ignore GROWUP_BONUS if we're already big if (type == GROWUP_BONUS) { - if (player_status->bonus == GROWUP_BONUS) - return true; - if (player_status->bonus == FIRE_BONUS) - return true; - if (player_status->bonus == ICE_BONUS) + if (!player_status->bonus == NO_BONUS) return true; } @@ -1010,7 +1050,7 @@ Player::set_bonus(BonusType type, bool animate) Vector pspeed = Vector(((dir==LEFT) ? +100 : -100), -300); Vector paccel = Vector(0, 1000); std::string action = (dir==LEFT)?"left":"right"; - Sector::current()->add_object(new SpriteParticle("images/objects/particles/firetux-helmet.sprite", action, ppos, ANCHOR_TOP, pspeed, paccel, LAYER_OBJECTS-1)); + Sector::current()->add_object(std::make_shared("images/objects/particles/firetux-helmet.sprite", action, ppos, ANCHOR_TOP, pspeed, paccel, LAYER_OBJECTS-1)); if (climbing) stop_climbing(*climbing); } if ((player_status->bonus == ICE_BONUS) && (animate)) { @@ -1019,24 +1059,46 @@ Player::set_bonus(BonusType type, bool animate) Vector pspeed = Vector(((dir==LEFT) ? +100 : -100), -300); Vector paccel = Vector(0, 1000); std::string action = (dir==LEFT)?"left":"right"; - Sector::current()->add_object(new SpriteParticle("images/objects/particles/icetux-cap.sprite", action, ppos, ANCHOR_TOP, pspeed, paccel, LAYER_OBJECTS-1)); + Sector::current()->add_object(std::make_shared("images/objects/particles/icetux-cap.sprite", action, ppos, ANCHOR_TOP, pspeed, paccel, LAYER_OBJECTS-1)); + if (climbing) stop_climbing(*climbing); + } + if ((player_status->bonus == AIR_BONUS) && (animate)) { + // visually lose hat + Vector ppos = Vector((bbox.p1.x + bbox.p2.x) / 2, bbox.p1.y); + Vector pspeed = Vector(((dir==LEFT) ? +100 : -100), -300); + Vector paccel = Vector(0, 1000); + std::string action = (dir==LEFT)?"left":"right"; + Sector::current()->add_object(std::make_shared("images/objects/particles/icetux-cap.sprite", action, ppos, ANCHOR_TOP, pspeed, paccel, LAYER_OBJECTS-1)); + if (climbing) stop_climbing(*climbing); + } + if ((player_status->bonus == EARTH_BONUS) && (animate)) { + // visually lose hard-hat + Vector ppos = Vector((bbox.p1.x + bbox.p2.x) / 2, bbox.p1.y); + Vector pspeed = Vector(((dir==LEFT) ? +100 : -100), -300); + Vector paccel = Vector(0, 1000); + std::string action = (dir==LEFT)?"left":"right"; + Sector::current()->add_object(std::make_shared("images/objects/particles/firetux-helmet.sprite", action, ppos, ANCHOR_TOP, pspeed, paccel, LAYER_OBJECTS-1)); if (climbing) stop_climbing(*climbing); } player_status->max_fire_bullets = 0; player_status->max_ice_bullets = 0; + player_status->max_air_time = 0; + player_status->max_earth_time = 0; } if (type == FIRE_BONUS) player_status->max_fire_bullets++; if (type == ICE_BONUS) player_status->max_ice_bullets++; + if (type == AIR_BONUS) player_status->max_air_time++; + if (type == EARTH_BONUS) player_status->max_earth_time++; player_status->bonus = type; return true; } void -Player::set_visible(bool visible) +Player::set_visible(bool visible_) { - this->visible = visible; - if( visible ) + this->visible = visible_; + if( visible_ ) set_group(COLGROUP_MOVING); else set_group(COLGROUP_DISABLED); @@ -1077,6 +1139,10 @@ Player::draw(DrawingContext& context) sa_prefix = "fire"; else if (player_status->bonus == ICE_BONUS) sa_prefix = "ice"; + else if (player_status->bonus == AIR_BONUS) + sa_prefix = "ice"; + else if (player_status->bonus == EARTH_BONUS) + sa_prefix = "fire"; else sa_prefix = "small"; @@ -1163,6 +1229,13 @@ Player::draw(DrawingContext& context) ; // don't draw Tux else { sprite->draw(context, get_pos(), LAYER_OBJECTS + 1); + // draw light with earthflower bonus + if (player_status->bonus == EARTH_BONUS){ + context.push_target(); + context.set_target(DrawingContext::LIGHTMAP); + lightsprite->draw(context, get_pos() + Vector(dir==LEFT ? 0 : 32, 0), 0); + context.pop_target(); + } } } @@ -1184,7 +1257,7 @@ Player::collision_tile(uint32_t tile_attributes) if( tile_attributes & Tile::WATER ){ swimming = true; no_water = false; - sound_manager->play( "sounds/splash.ogg" ); + SoundManager::current()->play( "sounds/splash.ogg" ); } } #endif @@ -1205,17 +1278,17 @@ Player::collision_solid(const CollisionHit& hit) on_ground_flag = true; floor_normal = hit.slope_normal; - // Butt Jump landed + // Butt Jump landed if (does_buttjump) { does_buttjump = false; physic.set_velocity_y(-300); on_ground_flag = false; - Sector::current()->add_object(new Particles( + Sector::current()->add_object(std::make_shared( Vector(get_bbox().p2.x, get_bbox().p2.y), 270+20, 270+40, Vector(280, -260), Vector(0, 300), 3, Color(.4f, .4f, .4f), 3, .8f, LAYER_OBJECTS+1)); - Sector::current()->add_object(new Particles( + Sector::current()->add_object(std::make_shared( Vector(get_bbox().p1.x, get_bbox().p2.y), 90-40, 90-20, Vector(280, -260), Vector(0, 300), 3, Color(.4f, .4f, .4f), 3, .8f, @@ -1284,7 +1357,7 @@ Player::collision(GameObject& other, const CollisionHit& hit) void Player::make_invincible() { - sound_manager->play("sounds/invincible_start.ogg"); + SoundManager::current()->play("sounds/invincible_start.ogg"); invincible_timer.start(TUX_INVINCIBLE_TIME); Sector::current()->play_music(HERRING_MUSIC); } @@ -1305,11 +1378,15 @@ Player::kill(bool completely) physic.set_velocity_x(0); + sprite->set_angle(0.0f); + if(!completely && is_big()) { - sound_manager->play("sounds/hurt.wav"); + SoundManager::current()->play("sounds/hurt.wav"); if(player_status->bonus == FIRE_BONUS - || player_status->bonus == ICE_BONUS) { + || player_status->bonus == ICE_BONUS + || player_status->bonus == AIR_BONUS + || player_status->bonus == EARTH_BONUS) { safe_timer.start(TUX_SAFE_TIME); set_bonus(GROWUP_BONUS, true); } else if(player_status->bonus == GROWUP_BONUS) { @@ -1325,7 +1402,7 @@ Player::kill(bool completely) duck = false; } } else { - sound_manager->play("sounds/kill.wav"); + SoundManager::current()->play("sounds/kill.wav"); // do not die when in edit mode if (edit_mode) { @@ -1338,7 +1415,7 @@ Player::kill(bool completely) for (int i = 0; i < 5; i++) { // the numbers: starting x, starting y, velocity y - Sector::current()->add_object(new FallingCoin(get_pos() + + Sector::current()->add_object(std::make_shared(get_pos() + Vector(graphicsRandom.rand(5), graphicsRandom.rand(-32,18)), graphicsRandom.rand(-100,100))); } @@ -1361,7 +1438,7 @@ Player::kill(bool completely) // TODO: need nice way to handle players dying in co-op mode Sector::current()->effect->fade_out(3.0); - sound_manager->stop_music(3.0); + SoundManager::current()->stop_music(3.0); } } @@ -1426,7 +1503,7 @@ Player::add_velocity(const Vector& velocity, const Vector& end_speed) physic.set_velocity_y(std::max(physic.get_velocity_y() + velocity.y, end_speed.y)); } -Vector +Vector Player::get_velocity() { return physic.get_velocity(); @@ -1435,10 +1512,12 @@ Player::get_velocity() void Player::bounce(BadGuy& ) { - if(controller->hold(Controller::JUMP)) - physic.set_velocity_y(-520); - else - physic.set_velocity_y(-300); + if(!(player_status->bonus == AIR_BONUS)) + physic.set_velocity_y(controller->hold(Controller::JUMP) ? -520 : -300); + else { + physic.set_velocity_y(controller->hold(Controller::JUMP) ? -580 : -340); + glide_time = player_status->max_air_time * GLIDE_TIME_PER_FLOWER; + } } //scripting Functions Below @@ -1501,7 +1580,7 @@ Player::set_edit_mode(bool enable) edit_mode = enable; } -void +void Player::start_climbing(Climbable& climbable) { if (climbing || !&climbable) return; @@ -1517,14 +1596,14 @@ Player::start_climbing(Climbable& climbable) } } -void +void Player::stop_climbing(Climbable& /*climbable*/) { if (!climbing) return; climbing = 0; - if (grabbed_object) { + if (grabbed_object) { grabbed_object->ungrab(*this, dir); grabbed_object = NULL; } @@ -1568,7 +1647,7 @@ Player::handle_input_climbing() if (can_jump) { stop_climbing(*climbing); return; - } + } } else { can_jump = true; }