Skip to content

Another attempt to fix wind #3268

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

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
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
38 changes: 20 additions & 18 deletions src/object/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const float OVERSPEED_DECELERATION = 100;

/** multiplied by WALK_ACCELERATION to give friction */
const float NORMAL_FRICTION_MULTIPLIER = 1.5f;
const float STATIC_FRICTION_MULTIPLIER = 2.0f;
/** multiplied by WALK_ACCELERATION to give friction */
const float ICE_FRICTION_MULTIPLIER = 0.1f;
const float ICE_ACCELERATION_MULTIPLIER = 0.25f;
Expand Down Expand Up @@ -629,7 +630,7 @@ Player::update(float dt_sec)
}

if (!m_dying && !m_deactivated)
handle_input();
handle_input(dt_sec);

/*
// handle_input() calls apply_friction() when Tux is not walking, so we'll have to do this ourselves
Expand Down Expand Up @@ -956,7 +957,7 @@ Player::update(float dt_sec)
}

void
Player::slide()
Player::slide(float dt_sec)
{
if (m_swimming || m_water_jump || m_stone)
{
Expand Down Expand Up @@ -1005,7 +1006,7 @@ Player::slide()
if (m_floor_normal.y == 0.f && m_can_jump)
{
if (!m_slidejumping && !m_jumping) {
apply_friction();
apply_friction(dt_sec);
}
}
else
Expand Down Expand Up @@ -1158,30 +1159,31 @@ Player::swim(float pointx, float pointy, bool boost)
}

void
Player::apply_friction()
Player::apply_friction(float dt_sec)
{
bool is_on_ground = on_ground();
float velx = m_physic.get_velocity_x();
if (is_on_ground && (fabsf(velx) < (m_stone ? 5.f : WALK_SPEED))) {
/*if (is_on_ground && (fabsf(velx) < (m_stone ? 5.f : WALK_SPEED))) {
m_physic.set_velocity_x(0);
m_physic.set_acceleration_x(0);
return;
}
}*/
float friction = WALK_ACCELERATION_X;
if (m_on_ice && is_on_ground)
//we need this or else sliding on ice will cause Tux to go on for a very long time
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));
if (is_on_ground && (fabsf(velx) < (m_stone ? 5.f : WALK_SPEED))) friction *= STATIC_FRICTION_MULTIPLIER;
if (velx < 0) {
m_physic.set_acceleration_x(friction);
m_physic.accelerate_x(friction, dt_sec, 0.0f);
} else if (velx > 0) {
m_physic.set_acceleration_x(-friction);
m_physic.accelerate_x(-friction, dt_sec, 0.0f);
} // no friction for physic.get_velocity_x() == 0
}

void
Player::handle_horizontal_input()
Player::handle_horizontal_input(float dt_sec)
{
float vx = m_physic.get_velocity_x();
float vy = m_physic.get_velocity_y();
Expand Down Expand Up @@ -1295,7 +1297,7 @@ Player::handle_horizontal_input()

// we get slower when not pressing any keys
if (dirsign == 0) {
apply_friction();
apply_friction(dt_sec);
}
}

Expand Down Expand Up @@ -1538,7 +1540,7 @@ Player::handle_vertical_input()
}

void
Player::handle_input()
Player::handle_input(float dt_sec)
{
// Display the player's ID on top of them at the beginning of the level/sector
// and persist the number until the player moves, because players will be
Expand All @@ -1560,7 +1562,7 @@ Player::handle_input()
return;
}
if (m_stone) {
handle_input_rolling();
handle_input_rolling(dt_sec);
return;
}
if (m_swimming) {
Expand Down Expand Up @@ -1607,7 +1609,7 @@ Player::handle_input()
m_peekingY = Direction::DOWN;

/* Handle horizontal movement: */
if (!m_backflipping && !m_stone && !m_swimming && !m_sliding) handle_horizontal_input();
if (!m_backflipping && !m_stone && !m_swimming && !m_sliding) handle_horizontal_input(dt_sec);

/* Jump/jumping? */
if (on_ground())
Expand Down Expand Up @@ -1654,7 +1656,7 @@ Player::handle_input()
}

if (m_stone)
apply_friction();
apply_friction(dt_sec);

/* Duck or Standup! */
if (((m_controller->pressed(Control::DOWN) && !m_growing && !m_stone) || ((m_duck || m_wants_buttjump || m_crawl) && m_controller->hold(Control::DOWN))) &&
Expand Down Expand Up @@ -1745,7 +1747,7 @@ Player::handle_input()
if (m_sliding)
{
adjust_height(DUCKED_TUX_HEIGHT);
slide();
slide(dt_sec);
}
else if (!m_sliding && (m_coyote_timer.started()) && !m_skidding_timer.started() &&
(m_floor_normal.y != 0 || (m_controller->hold(Control::LEFT) || m_controller->hold(Control::RIGHT)))
Expand All @@ -1754,7 +1756,7 @@ Player::handle_input()
{
sideways_push(m_dir == Direction::LEFT ? -100.f : 100.f);
adjust_height(DUCKED_TUX_HEIGHT);
slide();
slide(dt_sec);
}
}

Expand Down Expand Up @@ -2755,7 +2757,7 @@ Player::handle_input_climbing()
}

void
Player::handle_input_rolling()
Player::handle_input_rolling(float dt_sec)
{
// handle exiting
if (m_stone)
Expand Down Expand Up @@ -2834,7 +2836,7 @@ Player::handle_input_rolling()
m_physic.set_acceleration_x(ax + sx);
}
else {
apply_friction();
apply_friction(dt_sec);
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/object/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,14 +461,14 @@ class Player final : public MovingObject
bool track_state() const override { return false; }

private:
void handle_input();
void handle_input(float dt_sec);
void handle_input_ghost(); /**< input handling while in ghost mode */
void handle_input_climbing(); /**< input handling while climbing */
void handle_input_rolling();
void handle_input_rolling(float dt_sec);

void handle_input_swimming();

void handle_horizontal_input();
void handle_horizontal_input(float dt_sec);
void handle_vertical_input();

/** Set Tux's position, reset state and velocity. */
Expand All @@ -477,13 +477,13 @@ class Player final : public MovingObject
void do_jump_apex();
void early_jump_apex();

void slide();
void slide(float dt_sec);
void swim(float pointx, float pointy, bool boost);

BonusType string_to_bonus(const std::string& bonus) const;

/** slows Tux down a little, based on where he's standing */
void apply_friction();
void apply_friction(float dt_sec);

void check_bounds();

Expand Down
38 changes: 34 additions & 4 deletions src/object/wind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "object/sprite_particle.hpp"
#include "sprite/sprite.hpp"
#include "sprite/sprite_manager.hpp"
#include "supertux/physic.hpp"
#include "supertux/sector.hpp"
#include "util/reader_mapping.hpp"
#include "video/drawing_context.hpp"
Expand Down Expand Up @@ -132,6 +133,31 @@ Wind::draw(DrawingContext& context)
}
}

Vector
Wind::get_induced_acceleration(const Rectf& bbox, const Physic& physic) const
{
const float coef = 1/28.8;
const Vector rel_speed = speed - physic.get_velocity();
if (rel_speed.x == 0 && rel_speed.y == 0) {
return rel_speed; // no relative movement = no drag = no force = no acceleration
}
const float v2 = glm::length2(rel_speed);
const float v = std::sqrt(v2);
// "length" of the object in the direction of the wind
const float l = bbox.get_width() * std::fabs(rel_speed.x / v)
+ bbox.get_height() * std::fabs(rel_speed.y / v);
// induced acceleration
const float a = coef * v2 / l;
return a * (rel_speed / v);
}

void
Wind::accelerate_object(const MovingObject* other, Physic& physic)
{
const Vector acceleration = get_induced_acceleration(other->get_bbox(), physic);
physic.accelerate(acceleration, dt_sec, speed);
}

HitResponse
Wind::collision(MovingObject& other, const CollisionHit& )
{
Expand All @@ -141,7 +167,9 @@ Wind::collision(MovingObject& other, const CollisionHit& )
if (player && affects_player)
{
player->override_velocity();
if (!player->on_ground())
//player->add_velocity(get_induced_acceleration(player, player->get_physic()) * dt_sec, speed);
accelerate_object(player, player->get_physic());
/*if (!player->on_ground())
{
player->add_velocity(speed * acceleration * dt_sec, speed);
}
Expand All @@ -156,19 +184,21 @@ Wind::collision(MovingObject& other, const CollisionHit& )
// 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));
}
}
}*/
}

auto badguy = dynamic_cast<BadGuy*>(&other);
if (badguy && affects_badguys && badguy->can_be_affected_by_wind())
{
badguy->add_wind_velocity(speed * acceleration * dt_sec, speed);
//badguy->add_wind_velocity(get_induced_acceleration(badguy, badguy->get_physic()) * dt_sec, speed);
accelerate_object(badguy, badguy->get_physic());
}

auto rock = dynamic_cast<Rock*>(&other);
if (rock && affects_objects)
{
rock->add_wind_velocity(speed * acceleration * dt_sec, speed);
//rock->add_wind_velocity(get_induced_acceleration(rock, rock->get_physic()) * dt_sec, speed);
accelerate_object(rock, rock->get_physic());
}

return ABORT_MOVE;
Expand Down
8 changes: 7 additions & 1 deletion src/object/wind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "video/layer.hpp"

class Physic;
class ReaderMapping;

/** Defines an area that will gently push Players in one direction */
Expand Down Expand Up @@ -70,11 +71,14 @@ class Wind final : public MovingObject
*/
virtual int get_layer() const override { return m_layer; }

// Returns induced acceleration onto an object, approximated from maximal speeds and accelerations
Vector get_induced_acceleration(const Rectf& bbox, const Physic& physic) const;

private:
int m_layer;
bool blowing; /**< true if wind is currently switched on */
Vector speed;
float acceleration;
float acceleration; // legacy value
Vector new_size;

float dt_sec; /**< stores last dt_sec gotten at update() */
Expand All @@ -84,6 +88,8 @@ class Wind final : public MovingObject
bool affects_player; /**< whether the wind can affect the player: useful for cinematic wind */
bool fancy_wind;
bool particles_enabled;

void accelerate_object(const MovingObject* other, Physic& physic);

private:
Wind(const Wind&) = delete;
Expand Down
54 changes: 44 additions & 10 deletions src/supertux/physic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
#include "supertux/sector.hpp"

Physic::Physic() :
ax(0), ay(0),
vx(0), vy(0),
a(0, 0),
v(0, 0),
gravity_enabled_flag(true),
gravity_modifier(1.0f)
{
Expand All @@ -30,22 +30,20 @@ Physic::Physic() :
void
Physic::reset()
{
ax = ay = vx = vy = 0;
a.x = a.y = v.x = v.y = 0;
gravity_enabled_flag = true;
}

void
Physic::set_velocity(const Vector& vector)
{
vx = vector.x;
vy = vector.y;
v = vector;
}

void
Physic::set_acceleration(const Vector& vector)
{
ax = vector.x;
ay = vector.y;
a = vector;
}

Vector
Expand All @@ -56,11 +54,47 @@ Physic::get_movement(float dt_sec)
// Semi-implicit Euler integration
// with constant acceleration, this will result in a position delta of
// v t + .5 a t (t+dt_sec) at total time t
vx += ax * dt_sec;
vy += (ay + grav) * dt_sec;
Vector result(vx * dt_sec, vy * dt_sec);
v.x += a.x * dt_sec;
v.y += (a.y + grav) * dt_sec;
Vector result(v.x * dt_sec, v.y * dt_sec);

return result;
}

void
Physic::accelerate(const Vector& acceleration, float dt_sec, const Vector& target_velocity)
{
const Vector v_contr = acceleration * dt_sec;
const Vector new_v = v + v_contr;
if (glm::dot(v_contr, target_velocity - new_v) < 0) {
v = target_velocity; // overshot detected, trimming velocity
} else {
v = new_v;
}
}

void
Physic::accelerate_x(float acceleration, float dt_sec, float target_velocity)
{
const float v_contr = acceleration * dt_sec;
const float new_v = v.x + v_contr;
if (v_contr * (target_velocity - new_v) < 0) {
v.x = target_velocity;
} else {
v.x = new_v;
}
}

void
Physic::accelerate_y(float acceleration, float dt_sec, float target_velocity)
{
const float v_contr = acceleration * dt_sec;
const float new_v = v.y + v_contr;
if (v_contr * (target_velocity - new_v) < 0) {
v.y = target_velocity;
} else {
v.y = new_v;
}
}

/* EOF */
Loading
Loading