diff --git a/src/supertux/constants.hpp b/src/supertux/constants.hpp index cf22817f11..f2624c06e1 100644 --- a/src/supertux/constants.hpp +++ b/src/supertux/constants.hpp @@ -19,10 +19,9 @@ #include -// the engine will be run with a logical framerate of 64fps. -// We chose 64fps here because it is a power of 2, so 1/64 gives an "even" -// binary fraction... -static const float LOGICAL_FPS = 64.0; +// the engine will be run with a logical framerate of 66.666fps, corresponding +// to a 15 msec gap between steps. Warning: changing this may affect physics +static const float LOGICAL_FPS = 1000.0f / 15.0f; // SHIFT_DELTA is used for sliding over 1-tile gaps and collision detection static const float SHIFT_DELTA = 7.0f; diff --git a/src/supertux/screen_manager.cpp b/src/supertux/screen_manager.cpp index 1343af44ac..e53cfcbfdc 100644 --- a/src/supertux/screen_manager.cpp +++ b/src/supertux/screen_manager.cpp @@ -137,10 +137,9 @@ ScreenManager::ScreenManager(VideoSystem& video_system, InputManager& input_mana m_menu_manager(new MenuManager()), m_controller_hud(new ControllerHUD), m_mobile_controller(), - last_ticks(0), - elapsed_ticks(0), - ms_per_step(static_cast(1000.0f / LOGICAL_FPS)), - seconds_per_step(static_cast(ms_per_step) / 1000.0f), + last_time(std::chrono::steady_clock::now()), + elapsed_time(0.0f), + seconds_per_step(1.0f / LOGICAL_FPS), m_fps_statistics(new FPS_Stats()), m_speed(1.0), m_actions(), @@ -563,23 +562,25 @@ ScreenManager::handle_screen_switch() void ScreenManager::loop_iter() { - Uint32 ticks = SDL_GetTicks(); - elapsed_ticks += ticks - last_ticks; - last_ticks = ticks; + auto now = std::chrono::steady_clock::now(); + auto nsecs = std::chrono::duration_cast(now - last_time).count(); + elapsed_time += 1e-9f * static_cast(nsecs); + g_real_time += 1e-9f * static_cast(nsecs); + last_time = now; - if (elapsed_ticks > ms_per_step * 8) { + if (elapsed_time > seconds_per_step * 8) { // when the game loads up or levels are switched the // elapsed_ticks grows extremely large, so we just ignore those // large time jumps - elapsed_ticks = 0; + elapsed_time = 0; } bool always_draw = g_debug.draw_redundant_frames || g_config->frame_prediction; - if (elapsed_ticks < ms_per_step && !always_draw) { + if (elapsed_time < seconds_per_step && !always_draw) { // Sleep a bit because not enough time has passed since the previous // logical game step - SDL_Delay(ms_per_step - elapsed_ticks); + SDL_Delay(static_cast(1000.0f * (seconds_per_step - elapsed_time))); return; } @@ -587,10 +588,8 @@ void ScreenManager::loop_iter() Integration::update_status_all(m_screen_stack.back()->get_status()); Integration::update_all(); - g_real_time = static_cast(ticks) / 1000.0f; - float speed_multiplier = g_debug.get_game_speed_multiplier(); - int steps = elapsed_ticks / ms_per_step; + int steps = static_cast(std::floor(elapsed_time / seconds_per_step)); // Do not calculate more than a few steps at once // The maximum number of steps executed before drawing a frame is @@ -624,14 +623,13 @@ void ScreenManager::loop_iter() g_game_time += dtime; process_events(); update_gamelogic(dtime); - elapsed_ticks -= ms_per_step; + elapsed_time -= seconds_per_step; } // When the game is laggy, real time may be >1 step after the game time // To avoid predicting positions too far ahead, when using frame prediction, // limit the draw time offset to at most one step. - Uint32 tick_offset = std::min(elapsed_ticks, ms_per_step); - float time_offset = m_speed * speed_multiplier * static_cast(tick_offset) / 1000.0f; + float time_offset = m_speed * speed_multiplier * std::min(elapsed_time, seconds_per_step); if ((steps > 0 && !m_screen_stack.empty()) || always_draw) { diff --git a/src/supertux/screen_manager.hpp b/src/supertux/screen_manager.hpp index b2e7ab46fa..1b1de08c35 100644 --- a/src/supertux/screen_manager.hpp +++ b/src/supertux/screen_manager.hpp @@ -18,6 +18,7 @@ #ifndef HEADER_SUPERTUX_SUPERTUX_SCREEN_MANAGER_HPP #define HEADER_SUPERTUX_SUPERTUX_SCREEN_MANAGER_HPP +#include #include #include @@ -80,9 +81,8 @@ class ScreenManager final : public Currenton std::unique_ptr m_controller_hud; MobileController m_mobile_controller; - Uint32 last_ticks; - Uint32 elapsed_ticks; - const Uint32 ms_per_step; + std::chrono::steady_clock::time_point last_time; + float elapsed_time; const float seconds_per_step; std::unique_ptr m_fps_statistics;