From 954f44d08366530d0dc9b6574f0831ec28e22929 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Mon, 7 Oct 2024 15:01:59 +0200 Subject: Restore the screen shake effect Now the experience mightes better with what it was before the logic update change (59a7d5c58f8b3af21b3e19d4e78f5653bf011bfb). The per-frame effect is reduced and less constant, based on a sine wave. The effect is no longer applied directly to the mPixelViewX/Y values, but is rather only taken into account when rendering the view. --- src/gui/viewport.cpp | 61 ++++++++++++++++++++++++++-------------------------- src/gui/viewport.h | 1 + 2 files changed, 32 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 6c8016dc..9c1d2c9f 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -136,25 +136,6 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) scrollFraction; } - // manage shake effect - for (auto i = mShakeEffects.begin(); i != mShakeEffects.end(); i++) - { - // The decay defines the reduction in amplitude per 10ms. Here - // we calculate the reduction based on the ticks. - const float decay = std::pow(i->decay, ticks); - - // apply the effect to viewport - mPixelViewX += i->x *= -decay; - mPixelViewY += i->y *= -decay; - - // check death conditions - if (std::abs(i->x) + std::abs(i->y) < 1.0f || - (i->timer.isSet() && i->timer.passed())) - { - i = mShakeEffects.erase(i); - } - } - // Auto center when player is off screen if ( player_x - mPixelViewX > graphics->getWidth() / 2 || mPixelViewX - player_x > graphics->getWidth() / 2 @@ -193,25 +174,45 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) } + int scrollX = static_cast(mPixelViewX); + int scrollY = static_cast(mPixelViewY); + + // manage shake effect + for (auto i = mShakeEffects.begin(); i != mShakeEffects.end(); ) + { + ShakeEffect &effect = *i; + effect.age += ticks; + + // The decay defines the reduction in amplitude per 10ms. Here + // we calculate the strength left over based on the age in ticks. + const float strength = std::pow(effect.decay, effect.age); + const float phase = std::sin(effect.age); + + // apply the effect to viewport + scrollX += strength * phase * effect.x; + scrollY += strength * phase * effect.y; + + // check death conditions + if (strength < 0.01f || (effect.timer.isSet() && effect.timer.passed())) + i = mShakeEffects.erase(i); + else + ++i; + } + // Draw tiles and sprites - mMap->draw(graphics, (int) mPixelViewX, (int) mPixelViewY); + mMap->draw(graphics, scrollX, scrollY); if (mDebugFlags) { if (mDebugFlags & (Map::DEBUG_GRID | Map::DEBUG_COLLISION_TILES)) - { - mMap->drawCollision(graphics, (int) mPixelViewX, - (int) mPixelViewY, mDebugFlags); - } + mMap->drawCollision(graphics, scrollX, scrollY, mDebugFlags); _drawDebugPath(graphics); } // Draw text if (textManager) - { - textManager->draw(graphics, (int) mPixelViewX, (int) mPixelViewY); - } + textManager->draw(graphics, scrollX, scrollY); // Draw player names, speech, and emotion sprite as needed for (auto actor : actorSpriteManager->getAll()) @@ -220,7 +221,7 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) continue; auto *being = static_cast(actor); - being->drawSpeech((int) mPixelViewX, (int) mPixelViewY); + being->drawSpeech(scrollX, scrollY); } if (mDebugFlags & Map::DEBUG_BEING_IDS) @@ -235,8 +236,8 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) const Vector &beingPos = being->getPosition(); std::string idString = toString(being->getId()); graphics->drawText(idString, - beingPos.x - mPixelViewX, - beingPos.y - mPixelViewY, + beingPos.x - scrollX, + beingPos.y - scrollY, gcn::Graphics::CENTER); } } diff --git a/src/gui/viewport.h b/src/gui/viewport.h index 53edb50f..ee7eb96f 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -209,6 +209,7 @@ class Viewport : public WindowContainer, public gcn::MouseListener, float x; float y; float decay; + float age = 0.0f; Timer timer; }; std::list mShakeEffects; -- cgit v1.2.3-70-g09d2