diff --git a/sphaira/include/app.hpp b/sphaira/include/app.hpp index 443d130..9fddba6 100644 --- a/sphaira/include/app.hpp +++ b/sphaira/include/app.hpp @@ -337,6 +337,8 @@ public: nj::Decoder m_decoder; #endif + double m_delta_time{}; + private: // from nanovg decko3d example by adubbz static constexpr unsigned NumFramebuffers = 2; static constexpr unsigned StaticCmdSize = 0x1000; diff --git a/sphaira/include/ui/types.hpp b/sphaira/include/ui/types.hpp index 605aba4..4275981 100644 --- a/sphaira/include/ui/types.hpp +++ b/sphaira/include/ui/types.hpp @@ -395,12 +395,12 @@ struct Controller { m_kup = 0; } - void UpdateButtonHeld(u64 buttons) { + void UpdateButtonHeld(u64 buttons, double delta) { if (m_kdown & buttons) { m_step = 50; m_counter = 0; } else if (m_kheld & buttons) { - m_counter += m_step; + m_counter += m_step * delta; if (m_counter >= m_MAX) { m_kdown |= m_kheld & buttons; @@ -411,10 +411,10 @@ struct Controller { } private: - static constexpr int m_MAX = 1000; - static constexpr int m_MAX_STEP = 250; - int m_step = 50; - int m_counter = 0; + static constexpr double m_MAX = 1000; + static constexpr double m_MAX_STEP = 250; + double m_step = 50; + double m_counter = 0; }; } // namespace sphaira diff --git a/sphaira/source/app.cpp b/sphaira/source/app.cpp index 55323e7..dddc06c 100644 --- a/sphaira/source/app.cpp +++ b/sphaira/source/app.cpp @@ -413,6 +413,14 @@ void on_i18n_change() { } // namespace void App::Loop() { + // adjust these if FPSlocker ever supports different min/max fps. + constexpr double min_delta = 1000.0 / 120.0; // 120 fps + constexpr double max_delta = 1000.0 / 15.0; // 15 fps + constexpr double target_delta = 1000.0 / 60.0; // 60 fps + + u64 start = armTicksToNs(armGetSystemTick()); + m_delta_time = 1.0; + while (!m_quit && appletMainLoop()) { if (m_widgets.empty()) { m_quit = true; @@ -497,6 +505,15 @@ void App::Loop() { this->Poll(); this->Update(); this->Draw(); + + // check how long this frame took. + const u64 now = armTicksToNs(armGetSystemTick()); + // convert to ns. + const double delta = (double)(now - start) / 1e+6; + // clamp and normalise to 1.0 as the target, higher values if we took too long. + m_delta_time = std::clamp(delta, min_delta, max_delta) / target_delta; + // save timestamp for next frame. + start = now; } } @@ -1024,7 +1041,7 @@ void App::Poll() { m_controller.m_kdown = padGetButtonsDown(&m_pad); m_controller.m_kheld = padGetButtons(&m_pad); m_controller.m_kup = padGetButtonsUp(&m_pad); - m_controller.UpdateButtonHeld(static_cast(Button::ANY_DIRECTION)); + m_controller.UpdateButtonHeld(static_cast(Button::ANY_DIRECTION), m_delta_time); } }