Skip to content

Wind and swimming updates #2793

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

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
44 changes: 34 additions & 10 deletions src/badguy/badguy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,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 @@ -410,6 +412,20 @@ BadGuy::active_update(float dt_sec)
}
}

void
BadGuy::handle_wind()
{
if (!m_col.m_colliding_wind.empty())
{
if (on_ground() && m_physic.get_wind_velocity_y() > 0.f)
m_physic.set_wind_velocity_y(0.f);
}
else {
m_physic.set_wind_velocity(Vector(0.f));
m_physic.set_wind_acceleration(0.0);
}
}

void
BadGuy::inactive_update(float )
{
Expand Down Expand Up @@ -1260,21 +1276,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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be calculated using your push_to_velocity function?

}


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);

inline Physic& get_physic() { return m_physic; }

Expand Down Expand Up @@ -265,6 +269,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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should depend on dt_sec.

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
26 changes: 17 additions & 9 deletions src/badguy/flyingsnowball.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,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
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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should depend on dt_sec.

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

BadGuy::active_update(dt_sec);
}

bool
KamikazeSnowball::collision_squished(MovingObject& 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
16 changes: 16 additions & 0 deletions src/collision/collision_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
#include "collision/collision_object.hpp"

#include "collision/collision_movement_manager.hpp"
#include "object/wind.hpp"
#include "supertux/moving_object.hpp"

CollisionObject::CollisionObject(CollisionGroup group, MovingObject& parent) :
m_parent(parent),
m_bbox(),
m_colliding_wind(),
m_group(group),
m_movement(0.0f, 0.0f),
m_dest(),
Expand All @@ -48,6 +50,9 @@ CollisionObject::collides(CollisionObject& other, const CollisionHit& hit) const
HitResponse
CollisionObject::collision(CollisionObject& other, const CollisionHit& hit)
{
if(dynamic_cast<Wind*>(&other.m_parent)) {
collide_wind(other);
}
return m_parent.collision(other.m_parent, hit);
}

Expand All @@ -71,6 +76,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 @@ -60,6 +60,10 @@ class CollisionObject
m_ground_movement_manager = movement_manager;
}

void collide_wind(CollisionObject& other);

void clear_wind_collision_list();

void clear_bottom_collision_list();

inline bool is_unisolid() const { return m_unisolid; }
Expand Down Expand Up @@ -145,6 +149,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
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty much like:

if (glm::dot(to - from, from) > 0) {
  return move_towards(from, to, d);
} else {
  return from;
}

}

} // namespace math

#endif
Expand Down
22 changes: 21 additions & 1 deletion src/object/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@

#include "object/player.hpp"

#include <algorithm>

#include <glm/geometric.hpp>

#include <simplesquirrel/class.hpp>
#include <simplesquirrel/vm.hpp>

Expand All @@ -27,6 +31,7 @@
#include "editor/editor.hpp"
#include "math/util.hpp"
#include "math/random.hpp"
#include "math/vector.hpp"
#include "object/brick.hpp"
#include "object/bullet.hpp"
#include "object/camera.hpp"
Expand All @@ -40,6 +45,7 @@
#include "sprite/sprite.hpp"
#include "sprite/sprite_manager.hpp"
#include "supertux/constants.hpp"
#include "supertux/direction.hpp"
#include "supertux/game_session.hpp"
#include "supertux/gameconfig.hpp"
#include "supertux/resources.hpp"
Expand Down Expand Up @@ -379,6 +385,11 @@ Player::trigger_sequence(Sequence seq, const SequenceData* data)
void
Player::update(float dt_sec)
{
if (m_col.m_colliding_wind.empty()) {
m_physic.set_wind_acceleration(0);
m_physic.set_wind_velocity(0, 0);
}

if (is_dead() || Sector::get().get_object_count<Player>() == 1)
{
m_tag_timer.stop();
Expand Down Expand Up @@ -1173,6 +1184,11 @@ Player::apply_friction()
friction *= (ICE_FRICTION_MULTIPLIER*(m_sliding ? 4.f : m_stone ? 5.f : 1.f));
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!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Air drag depends on the object speed with respect to the air. If the velocity of the air is equal to the velocity of Tux, then indeed, there is no drag. However, when they have both different velocities, there is drag. That is actually the reason why wind blows object away.

However, it looks like the term friction stands for the friction between Tux and the ground. In such a case, the friction is one force and the air drag is another force.

if (!is_on_ground && !m_col.m_colliding_wind.empty() && std::abs(m_physic.get_wind_velocity_x()) > 0.f)
friction = 0.f;

if (velx < 0) {
m_physic.set_acceleration_x(friction);
} else if (velx > 0) {
Expand Down Expand Up @@ -1263,7 +1279,11 @@ Player::handle_horizontal_input()
// let's skid!
if (fabsf(vx)>SKID_XM && !m_skidding_timer.started()) {
m_skidding_timer.start(SKID_TIME);
SoundManager::current()->play("sounds/skid.wav", get_pos());

// skidding sound disabled in wind because it becomes too repetitive
if (m_col.m_colliding_wind.empty())
SoundManager::current()->play("sounds/skid.wav", get_pos());

// dust some particles
Sector::get().add<Particles>(
Vector(m_dir == Direction::LEFT ? m_col.m_bbox.get_right() : m_col.m_bbox.get_left(), m_col.m_bbox.get_bottom()),
Expand Down
Loading
Loading