Skip to content

Commit

Permalink
Smooth badguy and other object motion when frame prediction is on
Browse files Browse the repository at this point in the history
This commit extrapolates the drawn position for badguys and some other
moving objects, making their motion look smoother when both the frame
rate is high and frame prediction is on. This is already being done for
Tux, but that is not enough to always produce the illusion of smooth
motion. Without this commit one can at high frame rates see choppy
motion on carried objects when Tux is running, and on quickly moving
badguys, like MrIceBlock.
  • Loading branch information
mstoeckl committed Aug 20, 2024
1 parent c39b073 commit 4231287
Show file tree
Hide file tree
Showing 11 changed files with 42 additions and 16 deletions.
19 changes: 12 additions & 7 deletions src/badguy/badguy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "object/water_drop.hpp"
#include "sprite/sprite.hpp"
#include "sprite/sprite_manager.hpp"
#include "supertux/constants.hpp"
#include "supertux/level.hpp"
#include "supertux/sector.hpp"
#include "supertux/tile.hpp"
Expand Down Expand Up @@ -141,10 +142,13 @@ BadGuy::draw(DrawingContext& context)
{
if (!m_sprite.get()) return;

Vector draw_offset = context.get_time_offset() * m_physic.get_velocity();
Vector draw_pos = get_pos() + draw_offset;

if (m_state == STATE_INIT || m_state == STATE_INACTIVE)
{
if (Editor::is_active()) {
m_sprite->draw(context.color(), get_pos(), m_layer, m_flip);
m_sprite->draw(context.color(), draw_pos, m_layer, m_flip);
}
}
else
Expand All @@ -153,27 +157,27 @@ BadGuy::draw(DrawingContext& context)
{
context.push_transform();
context.set_flip(context.get_flip() ^ VERTICAL_FLIP);
m_sprite->draw(context.color(), get_pos(), m_layer, m_flip);
m_sprite->draw(context.color(), draw_pos, m_layer, m_flip);
context.pop_transform();
}
else
{
if (m_unfreeze_timer.started() && m_unfreeze_timer.get_timeleft() <= 1.f)
{
m_sprite->draw(context.color(), get_pos() + Vector(graphicsRandom.randf(-3, 3), 0.f), m_layer-1, m_flip);
m_sprite->draw(context.color(), draw_pos + Vector(graphicsRandom.randf(-3, 3), 0.f), m_layer - 1, m_flip);
if (is_portable())
m_freezesprite->draw(context.color(), get_pos() + Vector(graphicsRandom.randf(-3, 3), 0.f), m_layer);
m_freezesprite->draw(context.color(), draw_pos + Vector(graphicsRandom.randf(-3, 3), 0.f), m_layer);
}
else
{
if (m_frozen && is_portable())
m_freezesprite->draw(context.color(), get_pos(), m_layer);
m_sprite->draw(context.color(), get_pos(), m_layer - (m_frozen ? 1 : 0), m_flip);
m_freezesprite->draw(context.color(), draw_pos, m_layer);
m_sprite->draw(context.color(), draw_pos, m_layer - (m_frozen ? 1 : 0), m_flip);
}

if (m_glowing)
{
m_lightsprite->draw(context.light(), m_col.m_bbox.get_middle(), 0);
m_lightsprite->draw(context.light(), m_col.m_bbox.get_middle() + draw_offset, 0);
}
}
}
Expand Down Expand Up @@ -892,6 +896,7 @@ BadGuy::grab(MovingObject& object, const Vector& pos, Direction dir_)
{
Portable::grab(object, pos, dir_);
m_col.set_movement(pos - get_pos());
m_physic.set_velocity(m_col.get_movement() * LOGICAL_FPS);
m_dir = dir_;
if (m_frozen)
{
Expand Down
9 changes: 5 additions & 4 deletions src/badguy/crusher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,14 +468,15 @@ Crusher::spawn_roots(Direction direction)
void
Crusher::draw(DrawingContext& context)
{
m_sprite->draw(context.color(), get_pos(), m_layer + 2, m_flip);
Vector draw_pos = get_pos() + m_physic.get_velocity() * context.get_time_offset();
m_sprite->draw(context.color(), draw_pos, m_layer + 2, m_flip);
if (m_sprite->has_action("whites"))
{
// Draw crusher's eyes slightly behind.
m_lefteye->draw(context.color(), get_pos() + eye_position(false), m_layer + 1, m_flip);
m_righteye->draw(context.color(), get_pos() + eye_position(true), m_layer + 1, m_flip);
m_lefteye->draw(context.color(), draw_pos + eye_position(false), m_layer + 1, m_flip);
m_righteye->draw(context.color(), draw_pos + eye_position(true), m_layer + 1, m_flip);
// Draw the whites of crusher's eyes even further behind.
m_whites->draw(context.color(), get_pos(), m_layer, m_flip);
m_whites->draw(context.color(), draw_pos, m_layer, m_flip);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/badguy/mrbomb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "object/portable.hpp"
#include "sprite/sprite.hpp"
#include "sprite/sprite_manager.hpp"
#include "supertux/constants.hpp"
#include "supertux/sector.hpp"
#include "util/reader_mapping.hpp"

Expand Down Expand Up @@ -242,6 +243,7 @@ MrBomb::grab(MovingObject& object, const Vector& pos, Direction dir_)
set_action(dir_);

m_col.set_movement(pos - get_pos());
m_physic.set_velocity(m_col.get_movement() * LOGICAL_FPS);
m_dir = dir_;
set_colgroup_active(COLGROUP_DISABLED);
}
Expand Down
2 changes: 2 additions & 0 deletions src/badguy/mriceblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "object/player.hpp"
#include "object/portable.hpp"
#include "sprite/sprite.hpp"
#include "supertux/constants.hpp"
#include "supertux/sector.hpp"

namespace {
Expand Down Expand Up @@ -356,6 +357,7 @@ MrIceBlock::grab(MovingObject& object, const Vector& pos, Direction dir_)

Portable::grab(object, pos, dir_);
m_col.set_movement(pos - get_pos());
m_physic.set_velocity(m_col.get_movement() * LOGICAL_FPS);
m_dir = dir_;
set_action("flat", m_dir, /* loops = */ -1);
set_state(ICESTATE_GRABBED);
Expand Down
3 changes: 2 additions & 1 deletion src/badguy/rcrystallo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ void
RCrystallo::draw(DrawingContext& context)
{
context.push_transform();
m_sprite->draw(context.color(), get_pos(), m_layer);
Vector draw_pos = get_pos() + m_physic.get_velocity() * context.get_time_offset();
m_sprite->draw(context.color(), draw_pos, m_layer);
context.pop_transform();
}

Expand Down
2 changes: 2 additions & 0 deletions src/badguy/snail.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "object/player.hpp"
#include "object/portable.hpp"
#include "sprite/sprite.hpp"
#include "supertux/constants.hpp"
#include "supertux/sector.hpp"

namespace {
Expand Down Expand Up @@ -390,6 +391,7 @@ Snail::grab(MovingObject& object, const Vector& pos, Direction dir_)
if (m_frozen)
BadGuy::grab(object, pos, dir_);
m_col.set_movement(pos - get_pos());
m_physic.set_velocity(m_col.get_movement() * LOGICAL_FPS);
m_dir = dir_;
if (!m_frozen)
{
Expand Down
1 change: 1 addition & 0 deletions src/object/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2017,6 +2017,7 @@ Player::draw(DrawingContext& context)
// if Tux is above camera, draw little "air arrow" to show where he is x-wise
if (m_col.m_bbox.get_bottom() - 16 < Sector::get().get_camera().get_translation().y) {
float px = m_col.m_bbox.get_left() + (m_col.m_bbox.get_right() - m_col.m_bbox.get_left() - static_cast<float>(m_airarrow.get()->get_width())) / 2.0f;
px += context.get_time_offset() * m_physic.get_velocity().x;
float py = Sector::get().get_camera().get_translation().y;
py += std::min(((py - (m_col.m_bbox.get_bottom() + 16)) / 4), 16.0f);
context.color().draw_surface(m_airarrow, Vector(px, py), LAYER_HUD - 1);
Expand Down
9 changes: 9 additions & 0 deletions src/object/rock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "object/lit_object.hpp"
#include "object/pushbutton.hpp"
#include "object/trampoline.hpp"
#include "supertux/constants.hpp"
#include "supertux/sector.hpp"
#include "supertux/tile.hpp"
#include "object/player.hpp"
Expand Down Expand Up @@ -229,6 +230,7 @@ Rock::grab(MovingObject& object, const Vector& pos, Direction dir_)
Portable::grab(object, pos, dir_);
Vector movement = pos - get_pos();
m_col.set_movement(movement);
physic.set_velocity(movement * LOGICAL_FPS);
last_movement = movement;
set_group(COLGROUP_TOUCHABLE); //needed for lanterns catching willowisps
on_ground = false;
Expand Down Expand Up @@ -272,6 +274,13 @@ Rock::ungrab(MovingObject& object, Direction dir)
Portable::ungrab(object, dir);
}

void
Rock::draw(DrawingContext& context)
{
Vector offset = physic.get_velocity() * context.get_time_offset();
m_sprite->draw(context.color(), get_pos() + offset, m_layer, m_flip);
}

ObjectSettings
Rock::get_settings()
{
Expand Down
1 change: 1 addition & 0 deletions src/object/rock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Rock : public MovingSprite,
virtual ObjectSettings get_settings() override;
virtual GameObjectTypes get_types() const override;
std::string get_default_sprite_name() const override;
void draw(DrawingContext& context) override;

/** Adds velocity from wind */
virtual void add_wind_velocity(const Vector& velocity, const Vector& end_speed);
Expand Down
3 changes: 2 additions & 1 deletion src/object/smoke_cloud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ SmokeCloud::update(float dt_sec)
void
SmokeCloud::draw(DrawingContext& context)
{
sprite->draw(context.color(), position, LAYER_OBJECTS + 1);
Vector draw_pos = position - Vector(0.0, 120.0) * std::min(context.get_time_offset(), timer.get_timeleft());
sprite->draw(context.color(), draw_pos, LAYER_OBJECTS + 1);
}

/* EOF */
7 changes: 4 additions & 3 deletions src/object/sprite_particle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,14 @@ SpriteParticle::update(float dt_sec)
void
SpriteParticle::draw(DrawingContext& context)
{
sprite->draw(context.color(), position, drawing_layer);
Vector draw_pos = position + velocity * context.get_time_offset();
sprite->draw(context.color(), draw_pos, drawing_layer);

//Sparkles glow in the dark
if (glow)
{
sprite->draw(context.light(), position, drawing_layer);
lightsprite->draw(context.light(), position + Vector(12, 12), 0);
sprite->draw(context.light(), draw_pos, drawing_layer);
lightsprite->draw(context.light(), draw_pos + Vector(12, 12), 0);
}

}
Expand Down

0 comments on commit 4231287

Please sign in to comment.