diff --git a/src/object/player.cpp b/src/object/player.cpp index ca76ac8112..b4b3a71008 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -38,6 +38,7 @@ #include "object/particles.hpp" #include "object/portable.hpp" #include "object/sprite_particle.hpp" +#include "object/wind.hpp" #include "sprite/sprite.hpp" #include "sprite/sprite_manager.hpp" #include "supertux/constants.hpp" @@ -97,6 +98,8 @@ const float MAX_WALLCLING_YM = 64; const float WALK_SPEED = 100; /** rate at which m_boost decreases */ const float BOOST_DECREASE_RATE = 500; +/** rate at which m_wind_accel decreases */ +const float WIND_DECEL_RATE = 1; /** rate at which the speed decreases if going above maximum */ const float OVERSPEED_DECELERATION = 100; @@ -185,6 +188,8 @@ Player::Player(PlayerStatus& player_status, const std::string& name_, int player m_in_walljump_tile(false), m_can_walljump(false), m_boost(0.f), + m_wind_boost(Vector(0.f, 0.f)), + m_wind_accel(0.f), m_speedlimit(0), //no special limit m_velocity_override(), m_scripting_controller_old(nullptr), @@ -426,6 +431,20 @@ Player::update(float dt_sec) }); } + Rectf wind_box = get_bbox(); + bool in_wind = false; + for (auto& wind : Sector::get().get_objects_by_type()) { + if (wind_box.overlaps(wind.get_bbox())) { + in_wind = true; + } + } + if (!in_wind && m_wind_accel > 0.f) { + // convert final wind boost to velocity + m_wind_accel = 0.f; + m_physic.set_velocity(m_physic.get_velocity() + (m_wind_boost)); + m_wind_boost = Vector(0.f, 0.f); + } + // Skip if in multiplayer respawn if (is_dead() && m_target && Sector::get().get_object_count([this](const Player& p) { return p.is_active() && &p != this; })) { @@ -766,7 +785,7 @@ Player::update(float dt_sec) } // calculate movement for this frame - m_col.set_movement(m_physic.get_movement(dt_sec) + Vector(m_boost * dt_sec, 0)); + m_col.set_movement(m_physic.get_movement(dt_sec) + Vector(m_boost * dt_sec, 0) + (m_wind_boost * dt_sec)); if (m_grabbed_object != nullptr && !m_dying) { @@ -2537,6 +2556,8 @@ Player::kill(bool completely) m_physic.set_velocity_x(0); m_boost = 0.f; + m_wind_accel = 0.f; + m_wind_boost = Vector(0.f, 0.f); m_sprite->set_angle(0.0f); //m_santahatsprite->set_angle(0.0f); @@ -2758,6 +2779,9 @@ Player::set_ghost_mode(bool enable) if (m_climbing) stop_climbing(*m_climbing); + m_wind_accel = 0.f; + m_wind_boost = Vector(0.f, 0.f); + ungrab_object(); if (enable) { diff --git a/src/object/player.hpp b/src/object/player.hpp index ca64c01eb1..a4fb74d15c 100644 --- a/src/object/player.hpp +++ b/src/object/player.hpp @@ -279,6 +279,14 @@ class Player final : public MovingSprite * @description Returns Tux’s velocity in Y direction. */ inline float get_velocity_y() const { return m_physic.get_velocity_y(); } + + inline Vector get_wind_boost() const { return m_wind_boost; } + + inline void set_wind_boost(Vector v) { m_wind_boost = v; } + + inline float get_wind_accel() const { return m_wind_accel; } + + inline void set_wind_accel(float a) { m_wind_accel = a; } /** * @scripting * @description Sets the velocity of the player to a programmable/variable speed. @@ -543,6 +551,8 @@ class Player final : public MovingSprite bool m_in_walljump_tile; bool m_can_walljump; float m_boost; + Vector m_wind_boost; + float m_wind_accel; float m_speedlimit; bool m_velocity_override; const Controller* m_scripting_controller_old; /**< Saves the old controller while the scripting_controller is used */ diff --git a/src/object/wind.cpp b/src/object/wind.cpp index eea307c1c9..1f4db0df85 100644 --- a/src/object/wind.cpp +++ b/src/object/wind.cpp @@ -106,7 +106,9 @@ Wind::get_types() const /* l10n: Note: "Current" refers to "water current" and is not meant to be understood in terms of time. */ - { "current", _("Current") } + { "current", _("Current") }, + { "wind_additive", _("Wind (Additive)") }, + { "current_additive", _("Current (Additive)") } }; } @@ -129,9 +131,11 @@ Wind::update(float dt_sec_) { const float angle = std::atan2(speed.y, speed.x) * float(180.0 / M_PI); switch (m_type) { + case WIND_ADDITIVE: case WIND: // Normal wind Sector::get().add("images/particles/wind.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, Vector(0, 0), m_layer, false, 0, Color::WHITE, angle); break; + case CURRENT_ADDITIVE: case CURRENT: // Current variant Sector::get().add("images/particles/water_piece1.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, Vector(0, 0), m_layer, false, 0, Color::WHITE, angle); break; @@ -152,22 +156,33 @@ Wind::collision(MovingObject& other, const CollisionHit& ) auto player = dynamic_cast (&other); if (player && affects_player) { - player->override_velocity(); - if (!player->on_ground()) - { - player->add_velocity(speed * acceleration * dt_sec, speed); - } - else - { - if (player->get_controller().hold(Control::RIGHT) || player->get_controller().hold(Control::LEFT)) - { - player->add_velocity(Vector(speed.x, 0) * acceleration * dt_sec, speed); - } - else + if (m_type != WIND_ADDITIVE && m_type != CURRENT_ADDITIVE) { + player->override_velocity(); + if (!player->on_ground()) + { + player->add_velocity(speed * acceleration * dt_sec, speed); + } + else { - // When on ground, get blown slightly differently, but the max speed is less than it would be otherwise seen as we take "friction" into account - player->add_velocity((Vector(speed.x, 0) * 0.1f) * (acceleration+1), (Vector(speed.x, speed.y) * 0.5f)); - } + if (player->get_controller().hold(Control::RIGHT) || player->get_controller().hold(Control::LEFT)) + { + player->add_velocity(Vector(speed.x, 0) * acceleration * dt_sec, speed); + } + else + { + // When on ground, get blown slightly differently, but the max speed is less than it would be otherwise seen as we take "friction" into account + player->add_velocity((Vector(speed.x, 0) * 0.1f) * (acceleration+1), (Vector(speed.x, speed.y) * 0.5f)); + } + } + } + else { + if (player->get_wind_accel() < 1.0f) { + player->set_wind_accel(std::min(1.0f, player->get_wind_accel() + (acceleration * dt_sec))); + } + player->set_wind_boost(speed * player->get_wind_accel() * Vector(player->on_ground() ? 0.5f : 1.0f, 1.0f)); + if (player->get_velocity_y() > 0.f && speed.y < 0.f && !player->is_swimming()) { // allow wind to push players up that are going down + player->get_physic().set_velocity_y(0.f); + } } } diff --git a/src/object/wind.hpp b/src/object/wind.hpp index 345dfcf665..acf603134c 100644 --- a/src/object/wind.hpp +++ b/src/object/wind.hpp @@ -86,6 +86,8 @@ class Wind final : public DraggableRegion enum Type { WIND, CURRENT, + WIND_ADDITIVE, + CURRENT_ADDITIVE }; private: