Skip to content

Commit

Permalink
Refactor wind logic
Browse files Browse the repository at this point in the history
Wind was integrated into the `Physic` class, meaning it can be accessed in the same manner as object velocity and acceleration.
  • Loading branch information
biggeryetbetter committed Oct 24, 2024
1 parent 32ac6d6 commit 56084a4
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 127 deletions.
37 changes: 4 additions & 33 deletions src/badguy/badguy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ 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 @@ -99,8 +97,6 @@ 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 @@ -414,14 +410,12 @@ 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);
if (on_ground() && m_physic.get_wind_velocity_y() > 0.f)
m_physic.set_wind_velocity_y(0.f);
}
else {
m_wind_velocity = Vector(0.f, 0.f);
m_wind_acceleration = 0.0;
m_physic.set_wind_velocity(Vector(0.f));
m_physic.set_wind_acceleration(0.0);
}
}

Expand Down Expand Up @@ -1209,29 +1203,6 @@ BadGuy::can_be_affected_by_wind() const
return true;
}

void
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 (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);
}


void
BadGuy::register_class(ssq::VM& vm)
{
Expand Down
6 changes: 0 additions & 6 deletions src/badguy/badguy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,6 @@ class BadGuy : public MovingSprite,
/** Returns true if the badguy can currently be affected by wind */
virtual bool can_be_affected_by_wind() const;

/** 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; }

protected:
Expand Down Expand Up @@ -266,9 +263,6 @@ 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
27 changes: 27 additions & 0 deletions src/math/vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,33 @@ inline Vector at_angle(Vector const& v, float angle)
return vec2_from_polar(glm::length(v), angle);
}

// Move vector towards a new vector by a scalar delta.
inline Vector move_towards(Vector const& from, Vector const& to, float d) {
// Based on Godot's implementation
Vector vd = to - from;
float len = vd.length();
return len <= d ? to : from + vd / len * d;
}

// Change a velocity vector towards another, but do not change a component towards zero unless their signs are opposite.
inline Vector push_to_velocity(Vector const& from, Vector const& to, float d) {
if (d == 0.f) return from;

Vector diff = glm::normalize(to - from) * d;
Vector result = from;

if (to.x > 0 && from.x < to.x)
result.x = std::min(from.x + diff.x, to.x);
if (to.x < 0 && from.x > to.x)
result.x = std::max(from.x + diff.x, to.x);
if (to.y > 0 && from.y < to.y)
result.y = std::min(from.y + diff.y, to.y);
if (to.y < 0 && from.y > to.y)
result.y = std::max(from.y + diff.y, to.y);

return result;
}

} // namespace math

#endif
Expand Down
52 changes: 8 additions & 44 deletions src/object/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,6 @@ Player::Player(PlayerStatus& player_status, const std::string& name_, int player
m_growing(false),
m_backflip_timer(),
m_physic(),
m_wind_velocity(),
m_wind_acceleration(),
m_visible(true),
m_grabbed_object(nullptr),
m_grabbed_object_remove_listener(new GrabListener(*this)),
Expand Down Expand Up @@ -396,8 +394,8 @@ void
Player::update(float dt_sec)
{
if (m_col.m_colliding_wind.empty()) {
m_wind_velocity = Vector(0.f, 0.f);
m_wind_acceleration = 0.0;
m_physic.set_wind_acceleration(0);
m_physic.set_wind_velocity(0, 0);
}

if (is_dead() || Sector::get().get_object_count<Player>() == 1)
Expand Down Expand Up @@ -571,12 +569,6 @@ Player::update(float dt_sec)
if (!m_dying && !m_deactivated)
handle_input();

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);
}
/*
// handle_input() calls apply_friction() when Tux is not walking, so we'll have to do this ourselves
if (deactivated)
Expand Down Expand Up @@ -1112,22 +1104,16 @@ Player::apply_friction()
else
friction *= (NORMAL_FRICTION_MULTIPLIER*(m_sliding ? 0.8f : m_stone ? 0.4f : 1.f));

// Air friction does not make sense when the air is moving with you!
if (!is_on_ground && !m_col.m_colliding_wind.empty() && std::abs(m_wind_velocity.x) > 0.f)
friction = 0.f;

if (m_swimming)
{
if (glm::length(m_wind_velocity) == 0.f) {
// Friction factor in water is how similar Tux's swimming direction is to his actual direction,
// mapped between 0.95 and 0.99. Tux is more aerodynamic going forwards than backwards.
Vector swimming_direction = math::vec2_from_polar(1.f, m_swimming_angle);
Vector fac = swimming_direction - glm::normalize(m_physic.get_velocity());
// Friction factor in water is how similar Tux's swimming direction is to his actual direction,
// mapped between 0.95 and 0.99. Tux is more aerodynamic going forwards than backwards.
Vector swimming_direction = math::vec2_from_polar(1.f, m_swimming_angle);
Vector fac = swimming_direction - glm::normalize(m_physic.get_velocity());

fac = Vector(0.99f) - glm::abs(fac) / 2.0f * 0.04;
fac = Vector(0.99f) - glm::abs(fac) / 2.0f * 0.04;

m_physic.set_velocity(m_physic.get_velocity() * fac);
}
m_physic.set_velocity(m_physic.get_velocity() * fac);
} else
{
if (velx < 0) {
Expand Down Expand Up @@ -3083,28 +3069,6 @@ Player::remove_collected_key(Key* key)
m_collected_keys.end());
}

void
Player::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 (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);
}

void
Player::register_class(ssq::VM& vm)
{
Expand Down
5 changes: 0 additions & 5 deletions src/object/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,6 @@ class Player final : public MovingObject
/** Adds velocity to the player until given end speed is reached */
void add_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);

/** Returns the current velocity of the player */
Vector get_velocity() const;
/**
Expand Down Expand Up @@ -541,8 +538,6 @@ class Player final : public MovingObject
Timer m_backflip_timer;

Physic m_physic;
Vector m_wind_velocity;
float m_wind_acceleration;
bool m_visible;

Portable* m_grabbed_object;
Expand Down
35 changes: 4 additions & 31 deletions src/object/rock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ Rock::Rock(const ReaderMapping& reader, const std::string& spritename) :
m_on_ground(false),
m_on_ice(false),
m_last_movement(0.0f, 0.0f),
m_wind_velocity(),
m_wind_acceleration(0.f),
m_on_grab_script(),
m_on_ungrab_script(),
m_running_grab_script(),
Expand Down Expand Up @@ -140,14 +138,12 @@ Rock::handle_wind()
{
if (!m_col.m_colliding_wind.empty())
{
if (m_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);
if (m_on_ground && m_physic.get_wind_velocity_y() > 0.f)
m_physic.set_wind_velocity_y(0.f);
}
else {
m_wind_velocity = Vector(0.f, 0.f);
m_wind_acceleration = 0.0;
m_physic.set_wind_velocity(Vector(0.f));
m_physic.set_wind_acceleration(0.0);
}
}

Expand Down Expand Up @@ -301,27 +297,4 @@ Rock::get_settings()
return result;
}

void
Rock::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 (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);
}


/* EOF */
4 changes: 0 additions & 4 deletions src/object/rock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ class Rock : public MovingSprite,
virtual GameObjectTypes get_types() const override;
std::string get_default_sprite_name() const override;

/** Adds velocity from wind */
virtual void add_wind_velocity(const float acceleration, const Vector& end_speed, const float dt_sec);
Physic& get_physic() { return m_physic; }

protected:
Expand All @@ -63,8 +61,6 @@ class Rock : public MovingSprite,
bool m_on_ground;
bool m_on_ice;
Vector m_last_movement;
Vector m_wind_velocity;
float m_wind_acceleration;
std::string m_on_grab_script;
std::string m_on_ungrab_script;
bool m_running_grab_script;
Expand Down
15 changes: 12 additions & 3 deletions src/object/wind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,10 @@ Wind::collision(GameObject& other, const CollisionHit& )
if (player && affects_player)
{
player->override_velocity();
player->add_wind_velocity(acceleration * get_wind_strength(player->get_bbox().get_middle()), speed, dt_sec);
player->get_physic().set_wind_acceleration(
this->acceleration * get_wind_strength(player->get_bbox().get_middle())
);
player->get_physic().set_wind_velocity(this->speed);
}

auto badguy = dynamic_cast<BadGuy*>(&other);
Expand All @@ -167,13 +170,19 @@ Wind::collision(GameObject& other, const CollisionHit& )
if (m_type == CURRENT && dynamic_cast<DiveMine*>(badguy)) { // Dive mines are not affected by currents
return ABORT_MOVE;
}
badguy->add_wind_velocity(acceleration * get_wind_strength(badguy->get_bbox().get_middle()), speed, dt_sec);
badguy->get_physic().set_wind_acceleration(
this->acceleration * get_wind_strength(badguy->get_bbox().get_middle())
);
badguy->get_physic().set_wind_velocity(this->speed);
}

auto rock = dynamic_cast<Rock*>(&other);
if (rock && affects_objects)
{
rock->add_wind_velocity(acceleration * get_wind_strength(rock->get_bbox().get_middle()), speed, dt_sec);
rock->get_physic().set_wind_acceleration(
this->acceleration * get_wind_strength(rock->get_bbox().get_middle())
);
rock->get_physic().set_wind_velocity(this->speed);
}

return ABORT_MOVE;
Expand Down
25 changes: 24 additions & 1 deletion src/supertux/physic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
Physic::Physic() :
ax(0), ay(0),
vx(0), vy(0),
wvx(0), wvy(0),
wa(0),
wind_enabled_flag(true),
gravity_enabled_flag(true),
gravity_modifier(1.0f)
{
Expand All @@ -30,7 +33,8 @@ Physic::Physic() :
void
Physic::reset()
{
ax = ay = vx = vy = 0;
ax = ay = vx = vy = wvx = wvy = wa = 0;
wind_enabled_flag = true;
gravity_enabled_flag = true;
}

Expand All @@ -48,6 +52,18 @@ Physic::set_velocity(const Vector& vector)
vy = vector.y;
}

void
Physic::set_wind_velocity(float nvx, float nvy) {
wvx = nvx;
wvy = nvy;
}

void
Physic::set_wind_velocity(const Vector& vector) {
wvx = vector.x;
wvy = vector.y;
}

void
Physic::set_acceleration(float nax, float nay)
{
Expand All @@ -72,6 +88,13 @@ Physic::get_movement(float dt_sec)
// v t + .5 a t (t+dt_sec) at total time t
vx += ax * dt_sec;
vy += (ay + grav) * dt_sec;

if (wind_enabled_flag) {
this->set_velocity(
math::push_to_velocity(this->get_velocity(), this->get_wind_velocity(), wa * dt_sec)
);
}

Vector result(vx * dt_sec, vy * dt_sec);

return result;
Expand Down
Loading

0 comments on commit 56084a4

Please sign in to comment.