diff --git a/Source/diablo.cpp b/Source/diablo.cpp index ece4410e1..ae1d2d33b 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -841,7 +841,7 @@ void RunGameLoop(interface_mode uMsg) bool drawGame = true; bool processInput = true; - bool runGameLoop = demo::IsRunning() ? demo::GetRunGameLoop(drawGame, processInput) : nthread_has_500ms_passed(); + bool runGameLoop = demo::IsRunning() ? demo::GetRunGameLoop(drawGame, processInput) : nthread_has_500ms_passed(&drawGame); if (demo::IsRecording()) demo::RecordGameLoopResult(runGameLoop); diff --git a/Source/nthread.cpp b/Source/nthread.cpp index d9c6eaf78..907e6cd88 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -212,7 +212,7 @@ void nthread_ignore_mutex(bool bStart) sgbThreadIsRunning = bStart; } -bool nthread_has_500ms_passed() +bool nthread_has_500ms_passed(bool *drawGame /*= nullptr*/) { int currentTickCount = SDL_GetTicks(); int ticksElapsed = currentTickCount - last_tick; @@ -234,6 +234,13 @@ bool nthread_has_500ms_passed() ticksElapsed = 0; } } + if (drawGame != nullptr) { + // Check if we missed a game tick. + // This can happen when we run a low-end device that can't render fast enough (typically 20fps). + // If this happens, try to speed-up the game by skipping the rendering. + // This avoids desyncs and hourglasses when running multiplayer and slowdowns in singleplayer. + *drawGame = ticksElapsed <= gnTickDelay; + } return ticksElapsed >= 0; } diff --git a/Source/nthread.h b/Source/nthread.h index b3f4724f5..e6c4b6c07 100644 --- a/Source/nthread.h +++ b/Source/nthread.h @@ -32,7 +32,7 @@ void nthread_ignore_mutex(bool bStart); * @brief Checks if it's time for the logic to advance * @return True if the engine should tick */ -bool nthread_has_500ms_passed(); +bool nthread_has_500ms_passed(bool *drawGame = nullptr); /** * @brief Updates the progress in time to the next game tick */