Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wind and swimming updates #2793

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
babcd01
Player no longer is slowed when working with wind
biggeryetbetter Nov 17, 2023
b6c89ce
Most flying enemies interact correctly with wind
biggeryetbetter Dec 15, 2023
ff25649
Current variant of wind and player fixes
biggeryetbetter Feb 23, 2024
5b40442
Swimming physics redone to work better with wind
biggeryetbetter Mar 19, 2024
e3f2392
Fix friction causing issues with swimming
biggeryetbetter Mar 26, 2024
9915c5c
Add feathering to wind and fix logic error
biggeryetbetter Mar 28, 2024
a50f5c3
Wind uses its own acceleration and Dive Mine fix
biggeryetbetter Mar 31, 2024
6e471d4
Fix jittering in wind
biggeryetbetter Apr 21, 2024
d61abb8
Merge branch 'SuperTux:master' into wind_fixes
biggeryetbetter May 9, 2024
6092b69
Merge branch 'SuperTux:master' into wind_fixes
biggeryetbetter May 24, 2024
9c46153
Merge branch 'master' into wind_fixes
biggeryetbetter Jul 6, 2024
e47610f
Improve wind-player interactions
biggeryetbetter Jun 1, 2024
1be22aa
Merge branch 'wind_fixes' of github.com:biggeryetbetter/supertux into…
biggeryetbetter Jul 6, 2024
ba6cee5
Code cleaning and enable wind for many badguys
biggeryetbetter Jul 10, 2024
233428b
Merge branch 'master' into wind_fixes
biggeryetbetter Aug 2, 2024
32ac6d6
Swimming behaves more like the original swimming
biggeryetbetter Aug 7, 2024
5d1bc5d
Refactor wind logic
biggeryetbetter Oct 24, 2024
07ee4ef
Make wind accelerate bigger
biggeryetbetter Oct 24, 2024
752b8f3
Merge commit '7140d53520207ed9c87114df1fb6db0fc25c56d1' into wind_fixes
biggeryetbetter Oct 27, 2024
7bc1615
Make swimming less sluggish
biggeryetbetter Oct 28, 2024
cbf24a5
Remove unused variable
biggeryetbetter Nov 14, 2024
9a8cff1
Reintroduce dive jumping
biggeryetbetter Nov 16, 2024
7bda0ef
Fixed floating point errors
biggeryetbetter Dec 1, 2024
fccd5a3
Reduce swimming speed and remove debugging leftovers
biggeryetbetter Dec 1, 2024
9ca056d
Merge commit 'e3dededd2d833261d425020f0149d3ef8d8f53db' into wind_fixes
biggeryetbetter Dec 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 40 additions & 10 deletions src/badguy/badguy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ BadGuy::BadGuy(const Vector& pos, Direction direction, const std::string& sprite
const std::string& light_sprite_name, const std::string& ice_sprite_name) :
MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED),
m_physic(),
m_wind_velocity(),
m_wind_acceleration(0.f),
m_countMe(true),
m_is_initialized(false),
m_start_position(m_col.m_bbox.p1()),
Expand Down Expand Up @@ -97,6 +99,8 @@ BadGuy::BadGuy(const ReaderMapping& reader, const std::string& sprite_name,
const std::string& light_sprite_name, const std::string& ice_sprite_name) :
MovingSprite(reader, sprite_name, layer, COLGROUP_DISABLED),
m_physic(),
m_wind_velocity(),
m_wind_acceleration(0.f),
m_countMe(true),
m_is_initialized(false),
m_start_position(m_col.m_bbox.p1()),
Expand Down Expand Up @@ -382,6 +386,8 @@ BadGuy::get_allowed_directions() const
void
BadGuy::active_update(float dt_sec)
{
handle_wind();

if (!is_grabbed())
{
if (is_in_water() && m_water_affected)
Expand All @@ -403,6 +409,22 @@ BadGuy::active_update(float dt_sec)
}
}

void
BadGuy::handle_wind()
{
if (!m_col.m_colliding_wind.empty())
{
if (on_ground() && m_wind_velocity.y > 0.f)
m_wind_velocity.y = 0.f;

m_physic.set_velocity(m_physic.get_velocity() + m_wind_velocity);
}
else {
m_wind_velocity = Vector(0.f, 0.f);
m_wind_acceleration = 0.0;
}
}

void
BadGuy::inactive_update(float )
{
Expand Down Expand Up @@ -1184,21 +1206,29 @@ BadGuy::after_editor_set()
bool
BadGuy::can_be_affected_by_wind() const
{
return !on_ground();
return true;
}

void
BadGuy::add_wind_velocity(const Vector& velocity, const Vector& end_speed)
BadGuy::add_wind_velocity(const float acceleration, const Vector& end_speed, const float dt_sec)
{
Vector adjusted_end_speed = glm::normalize(end_speed) * acceleration;

Vector vec_acceleration = adjusted_end_speed * dt_sec;

m_wind_acceleration = acceleration;
Vector end_velocity = Vector(0.f, 0.f);
// Only add velocity in the same direction as the wind.
if (end_speed.x > 0 && m_physic.get_velocity_x() < end_speed.x)
m_physic.set_velocity_x(std::min(m_physic.get_velocity_x() + velocity.x, end_speed.x));
if (end_speed.x < 0 && m_physic.get_velocity_x() > end_speed.x)
m_physic.set_velocity_x(std::max(m_physic.get_velocity_x() + velocity.x, end_speed.x));
if (end_speed.y > 0 && m_physic.get_velocity_y() < end_speed.y)
m_physic.set_velocity_y(std::min(m_physic.get_velocity_y() + velocity.y, end_speed.y));
if (end_speed.y < 0 && m_physic.get_velocity_y() > end_speed.y)
m_physic.set_velocity_y(std::max(m_physic.get_velocity_y() + velocity.y, end_speed.y));
if (adjusted_end_speed.x > 0 && m_physic.get_velocity_x() + m_wind_velocity.x < end_speed.x)
end_velocity.x = std::min(vec_acceleration.x, adjusted_end_speed.x);
if (adjusted_end_speed.x < 0 && m_physic.get_velocity_x() + m_wind_velocity.x > end_speed.x)
end_velocity.x = std::max(vec_acceleration.x, adjusted_end_speed.x);
if (adjusted_end_speed.y > 0 && m_physic.get_velocity_y() + m_wind_velocity.y < end_speed.y)
end_velocity.y = std::min(vec_acceleration.y, adjusted_end_speed.y);
if (adjusted_end_speed.y < 0 && m_physic.get_velocity_y() + m_wind_velocity.y > end_speed.y)
end_velocity.y = std::max(vec_acceleration.y, adjusted_end_speed.y);

m_wind_velocity = glm::lerp(m_wind_velocity, end_velocity, 0.5f);
}


Expand Down
11 changes: 9 additions & 2 deletions src/badguy/badguy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class BadGuy : public MovingSprite,
state and calls active_update and inactive_update */
virtual void update(float dt_sec) override;

/** Called each frame during active_update. Applies velocity from
* wind if the badguy is inside wind and resets it if not. */
virtual void handle_wind();

static std::string class_name() { return "badguy"; }
virtual std::string get_class_name() const override { return class_name(); }
virtual std::string get_exposed_class_name() const override { return "BadGuy"; }
Expand Down Expand Up @@ -154,8 +158,8 @@ class BadGuy : public MovingSprite,
/** Returns true if the badguy can currently be affected by wind */
virtual bool can_be_affected_by_wind() const;

/** Adds velocity from wind */
virtual void add_wind_velocity(const Vector& velocity, const Vector& end_speed);
/** Version of `add_velocity` with modifications for wind physics */
void add_wind_velocity(const float acceleration, const Vector& end_speed, const float dt_sec);

Physic& get_physic() { return m_physic; }

Expand Down Expand Up @@ -262,6 +266,9 @@ class BadGuy : public MovingSprite,
protected:
Physic m_physic;

Vector m_wind_velocity;
float m_wind_acceleration;

public:
/** Count this badguy to the statistics? This value should not be
changed during runtime. */
Expand Down
4 changes: 4 additions & 0 deletions src/badguy/dart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ void
Dart::active_update(float dt_sec)
{
BadGuy::active_update(dt_sec);

m_physic.set_velocity_y(m_physic.get_velocity_y() * 0.9f);
m_col.set_movement(m_physic.get_movement(dt_sec));

sound_source->set_position(get_pos());
}

Expand Down
7 changes: 6 additions & 1 deletion src/badguy/fish_harmless.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ void
FishHarmless::initialize()
{
FishSwimming::initialize();
set_colgroup_active(COLGROUP_MOVING_ONLY_STATIC);
set_colgroup_active(COLGROUP_MOVING);
}

HitResponse
FishHarmless::collision_player(Player& player, const CollisionHit& hit) {
return HitResponse::ABORT_MOVE;
}

/* EOF */
1 change: 1 addition & 0 deletions src/badguy/fish_harmless.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class FishHarmless final : public FishSwimming

protected:
virtual void initialize() override;
virtual HitResponse collision_player(Player& player, const CollisionHit& hit) override;

private:
FishHarmless(const FishHarmless&) = delete;
Expand Down
27 changes: 18 additions & 9 deletions src/badguy/flyingsnowball.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const float GLOBAL_SPEED_MULT = 0.8f; /**< The overall movement speed/rate. */
FlyingSnowBall::FlyingSnowBall(const ReaderMapping& reader) :
BadGuy(reader, "images/creatures/flying_snowball/flying_snowball.sprite"),
total_time_elapsed(),
prev_height(0.f),
puff_timer()
{
m_physic.enable_gravity(false);
Expand Down Expand Up @@ -75,16 +76,24 @@ FlyingSnowBall::active_update(float dt_sec)

float delta = total_time_elapsed * GLOBAL_SPEED_MULT;

// Put that function in a graphing calculator :
// Derivative of the following function (put it in a graphing calculator):
// sin(x)^3 + sin(3(x - pi/3))/3
float targetHgt = std::pow(std::sin(delta), 3.f) +
std::sin(3.f *
((delta - math::PI) / 3.f)
) / 3.f;
targetHgt = targetHgt * 100.f + m_start_position.y;
m_physic.set_velocity_y(targetHgt - get_pos().y);

m_col.set_movement(m_physic.get_movement(1.f));
float targetHgt = (
std::cos(3.f * (delta - math::PI/3.f))
+ std::pow(std::sin(delta), 2.f)
* std::cos(delta) * 3.f
);

// Simple damping and then movement
m_physic.set_velocity_y(m_physic.get_velocity_y() * pow(0.5f, dt_sec));
m_physic.set_velocity_y(m_physic.get_velocity_y() + targetHgt);

m_physic.set_velocity_x(m_physic.get_velocity_x() * pow(0.5f, dt_sec));

BadGuy::handle_wind();

m_col.set_movement(m_physic.get_movement(dt_sec));


auto player = get_nearest_player();
if (player) {
Expand Down
1 change: 1 addition & 0 deletions src/badguy/flyingsnowball.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class FlyingSnowBall final : public BadGuy

private:
float total_time_elapsed;
float prev_height;
Timer puff_timer; /**< time until the next smoke puff is spawned */

private:
Expand Down
9 changes: 9 additions & 0 deletions src/badguy/kamikazesnowball.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "badguy/kamikazesnowball.hpp"

#include "audio/sound_manager.hpp"
#include "supertux/direction.hpp"

namespace{
static const float KAMIKAZE_SPEED = 200;
Expand All @@ -39,6 +40,14 @@ KamikazeSnowball::initialize()
set_action(m_dir);
}

void
KamikazeSnowball::active_update(float dt_sec) {
m_physic.set_velocity_y(m_physic.get_velocity_y() * 0.9f);
m_col.set_movement(m_physic.get_movement(dt_sec));

BadGuy::active_update(dt_sec);
}

bool
KamikazeSnowball::collision_squished(GameObject& object)
{
Expand Down
1 change: 1 addition & 0 deletions src/badguy/kamikazesnowball.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class KamikazeSnowball : public BadGuy

virtual void initialize() override;
virtual void collision_solid(const CollisionHit& hit) override;
virtual void active_update(float dt_sec) override;
static std::string class_name() { return "kamikazesnowball"; }
virtual std::string get_class_name() const override { return class_name(); }
static std::string display_name() { return _("Kamikaze Snowball"); }
Expand Down
2 changes: 2 additions & 0 deletions src/badguy/owl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ Owl::is_above_player() const
void
Owl::active_update (float dt_sec)
{
m_physic.set_velocity_y(m_physic.get_velocity_y() * 0.9f);

BadGuy::active_update (dt_sec);

if (m_frozen)
Expand Down
1 change: 1 addition & 0 deletions src/badguy/stalactite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Stalactite::active_update(float dt_sec)
set_colgroup_active(COLGROUP_MOVING);
}
} else if (state == STALACTITE_FALLING) {
BadGuy::handle_wind();
m_col.set_movement(m_physic.get_movement(dt_sec));
}

Expand Down
6 changes: 6 additions & 0 deletions src/badguy/zeekling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ Zeekling::active_update(float dt_sec) {
BadGuy::active_update(dt_sec);
return;
} else if (state == DIVING) {
// Something took away our diving velocity so we should go back up.
if (m_physic.get_velocity_y() <= 0.0f) {
state = CLIMBING;
m_physic.set_velocity_y(-2*fabsf(m_physic.get_velocity_x()));
set_action(m_dir);
}
BadGuy::active_update(dt_sec);
return;
} else if (state == CLIMBING) {
Expand Down
16 changes: 16 additions & 0 deletions src/collision/collision_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@

#include "collision/collision_listener.hpp"
#include "collision/collision_movement_manager.hpp"
#include "object/wind.hpp"
#include "supertux/game_object.hpp"

CollisionObject::CollisionObject(CollisionGroup group, CollisionListener& listener) :
m_listener(listener),
m_bbox(),
m_colliding_wind(),
m_group(group),
m_movement(0.0f, 0.0f),
m_dest(),
Expand All @@ -49,6 +51,9 @@ CollisionObject::collides(CollisionObject& other, const CollisionHit& hit) const
HitResponse
CollisionObject::collision(CollisionObject& other, const CollisionHit& hit)
{
if(dynamic_cast<Wind*>(&other.m_listener)) {
collide_wind(other);
}
return m_listener.collision(dynamic_cast<GameObject&>(other.m_listener), hit);
}

Expand All @@ -72,6 +77,17 @@ void
CollisionObject::notify_object_removal(CollisionObject* other)
{
m_objects_hit_bottom.erase(other);
m_colliding_wind.erase(other);
}

void
CollisionObject::collide_wind(CollisionObject& other) {
m_colliding_wind.insert(&other);
}

void
CollisionObject::clear_wind_collision_list() {
m_colliding_wind.clear();
}

void
Expand Down
7 changes: 7 additions & 0 deletions src/collision/collision_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ class CollisionObject
m_ground_movement_manager = movement_manager;
}

void collide_wind(CollisionObject& other);

void clear_wind_collision_list();

void clear_bottom_collision_list();

bool is_unisolid() const { return m_unisolid; }
Expand Down Expand Up @@ -149,6 +153,9 @@ class CollisionObject
this isn't necessarily the bounding box for graphics) */
Rectf m_bbox;

/** All wind areas that the player is currently touching */
std::unordered_set<CollisionObject*> m_colliding_wind;

/** The collision group */
CollisionGroup m_group;

Expand Down
1 change: 1 addition & 0 deletions src/collision/collision_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ CollisionSystem::update()
object->m_pressure = Vector(0, 0);
object->m_dest.move(object->get_movement());
object->clear_bottom_collision_list();
object->clear_wind_collision_list();
}

// Part 1: COLGROUP_MOVING vs COLGROUP_STATIC and tilemap.
Expand Down
Loading
Loading