From 87784f423391af03a0f7583a706fc5720798e26d Mon Sep 17 00:00:00 2001 From: Daniel Ward <39805490+weluvgoatz@users.noreply.github.com> Date: Thu, 19 Feb 2026 13:15:45 -0800 Subject: [PATCH 1/7] Whee!!! (broken new player wind) --- src/object/player.cpp | 14 +++++++++++++- src/object/player.hpp | 10 ++++++++++ src/object/wind.cpp | 42 ++++++++++++++++++++++++++---------------- src/object/wind.hpp | 1 + 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/object/player.cpp b/src/object/player.cpp index ca76ac81128..594143002fb 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,13 @@ Player::update(float dt_sec) }); } + Rectf wind_box = get_bbox(); + for (auto& wind : Sector::get().get_objects_by_type()) { + if (!wind_box.overlaps(wind.get_bbox()) && m_wind_accel > 0.f) { + m_wind_accel = std::max(0.f, m_wind_accel - (WIND_DECEL_RATE * dt_sec)); + } + } + // 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 +778,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); if (m_grabbed_object != nullptr && !m_dying) { diff --git a/src/object/player.hpp b/src/object/player.hpp index ca64c01eb14..a4fb74d15c6 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 eea307c1c95..43efa6340df 100644 --- a/src/object/wind.cpp +++ b/src/object/wind.cpp @@ -106,7 +106,8 @@ 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") }, + { "new_wind", _("New Wind") } }; } @@ -129,6 +130,7 @@ Wind::update(float dt_sec_) { const float angle = std::atan2(speed.y, speed.x) * float(180.0 / M_PI); switch (m_type) { + case NEW_WIND: 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; @@ -152,22 +154,30 @@ 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 != NEW_WIND) { + 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() * (player->on_ground() ? 0.5f : 1.0f)); } } diff --git a/src/object/wind.hpp b/src/object/wind.hpp index 345dfcf6653..d40d3cab798 100644 --- a/src/object/wind.hpp +++ b/src/object/wind.hpp @@ -86,6 +86,7 @@ class Wind final : public DraggableRegion enum Type { WIND, CURRENT, + NEW_WIND }; private: From e5027ffe62ab73c867dbbf8709661578359e21da Mon Sep 17 00:00:00 2001 From: Daniel Ward <39805490+weluvgoatz@users.noreply.github.com> Date: Thu, 19 Feb 2026 14:05:22 -0800 Subject: [PATCH 2/7] Update player.cpp --- src/object/player.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/object/player.cpp b/src/object/player.cpp index 594143002fb..d93fac332a6 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -432,11 +432,17 @@ 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()) && m_wind_accel > 0.f) { - m_wind_accel = std::max(0.f, m_wind_accel - (WIND_DECEL_RATE * dt_sec)); - } + if (wind_box.overlaps(wind.get_bbox())) { + in_wind = true; } + } + if (!in_wind && m_wind_accel > 0.f) { + 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; })) @@ -778,7 +784,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_wind_boost); + 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) { @@ -2770,6 +2776,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) { From 7192d4b6f719e4930246970439264ae9541af2eb Mon Sep 17 00:00:00 2001 From: Daniel Ward <39805490+weluvgoatz@users.noreply.github.com> Date: Thu, 19 Feb 2026 15:31:57 -0800 Subject: [PATCH 3/7] Small updates - still doesn't work great. --- src/object/player.cpp | 1 + src/object/wind.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/object/player.cpp b/src/object/player.cpp index d93fac332a6..3a999d91ed3 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -439,6 +439,7 @@ Player::update(float dt_sec) } } 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); diff --git a/src/object/wind.cpp b/src/object/wind.cpp index 43efa6340df..83de78112dc 100644 --- a/src/object/wind.cpp +++ b/src/object/wind.cpp @@ -177,7 +177,7 @@ Wind::collision(MovingObject& other, const CollisionHit& ) 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() * (player->on_ground() ? 0.5f : 1.0f)); + player->set_wind_boost(speed * player->get_wind_accel() * Vector(player->on_ground() ? 0.5f : 1.0f, 1.0f)); } } From da1b68c473ae7e229b32d8efda6c1a81ddd7bc2e Mon Sep 17 00:00:00 2001 From: Daniel Ward <39805490+weluvgoatz@users.noreply.github.com> Date: Thu, 19 Feb 2026 15:39:34 -0800 Subject: [PATCH 4/7] Disobey gravity in wind --- src/object/wind.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/object/wind.cpp b/src/object/wind.cpp index 83de78112dc..cc90f4ce40c 100644 --- a/src/object/wind.cpp +++ b/src/object/wind.cpp @@ -178,6 +178,9 @@ Wind::collision(MovingObject& other, const CollisionHit& ) 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) { // allow wind to push players that are obeying gravity at the moment + player->get_physic().set_velocity_y(0.f); + } } } From 5fa47e4829c2c3e5781754f2889db88f9912fe92 Mon Sep 17 00:00:00 2001 From: Daniel Ward <39805490+weluvgoatz@users.noreply.github.com> Date: Thu, 19 Feb 2026 17:45:45 -0800 Subject: [PATCH 5/7] Separate wind into additive types --- src/object/wind.cpp | 10 ++++++---- src/object/wind.hpp | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/object/wind.cpp b/src/object/wind.cpp index cc90f4ce40c..3dc016633c8 100644 --- a/src/object/wind.cpp +++ b/src/object/wind.cpp @@ -107,7 +107,8 @@ Wind::get_types() const l10n: Note: "Current" refers to "water current" and is not meant to be understood in terms of time. */ { "current", _("Current") }, - { "new_wind", _("New Wind") } + { "wind_additive", _("Wind (Additive)") }, + { "current_additive", _("Current (Additive)") } }; } @@ -130,10 +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 NEW_WIND: + 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; @@ -154,7 +156,7 @@ Wind::collision(MovingObject& other, const CollisionHit& ) auto player = dynamic_cast (&other); if (player && affects_player) { - if (m_type != NEW_WIND) { + if (m_type != WIND_ADDITIVE && m_type != CURRENT_ADDITIVE) { player->override_velocity(); if (!player->on_ground()) { @@ -178,7 +180,7 @@ Wind::collision(MovingObject& other, const CollisionHit& ) 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) { // allow wind to push players that are obeying gravity at the moment + if (player->get_velocity_y() > 0.f && speed.y < 0.f) { // 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 d40d3cab798..acf603134c6 100644 --- a/src/object/wind.hpp +++ b/src/object/wind.hpp @@ -86,7 +86,8 @@ class Wind final : public DraggableRegion enum Type { WIND, CURRENT, - NEW_WIND + WIND_ADDITIVE, + CURRENT_ADDITIVE }; private: From e9ebefe1c58de4dfa05ae05ab5391e22d687037e Mon Sep 17 00:00:00 2001 From: Daniel Ward <39805490+weluvgoatz@users.noreply.github.com> Date: Thu, 19 Feb 2026 17:48:56 -0800 Subject: [PATCH 6/7] Don't push Tux when dead --- src/object/player.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/object/player.cpp b/src/object/player.cpp index 3a999d91ed3..b4b3a710081 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -2556,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); From dc7d66bdfff918217ba2e08b9674c65dbed4938d Mon Sep 17 00:00:00 2001 From: Daniel Ward <39805490+weluvgoatz@users.noreply.github.com> Date: Thu, 19 Feb 2026 18:18:25 -0800 Subject: [PATCH 7/7] Don't care about down velocity when swimming --- src/object/wind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object/wind.cpp b/src/object/wind.cpp index 3dc016633c8..1f4db0df85f 100644 --- a/src/object/wind.cpp +++ b/src/object/wind.cpp @@ -180,7 +180,7 @@ Wind::collision(MovingObject& other, const CollisionHit& ) 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) { // allow wind to push players up that are going down + 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); } }