diff --git a/changes/autoexplore-delay.md b/changes/autoexplore-delay.md new file mode 100644 index 00000000..65ca7355 --- /dev/null +++ b/changes/autoexplore-delay.md @@ -0,0 +1 @@ +Animations such as autoexplore and using a staff now run at the same speed regardless of game performance (up to a limit). diff --git a/src/platform/curses-platform.c b/src/platform/curses-platform.c index 3ea092e7..4f994414 100644 --- a/src/platform/curses-platform.c +++ b/src/platform/curses-platform.c @@ -113,9 +113,24 @@ static uint64_t getTime() { return (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; } +static long lastDelayTime = 0; + +// Like SDL_Delay, but reduces the delay if time has passed since the last delay +static void _delayUpTo(short ms) { + long curTime = getTime(); + long timeDiff = curTime - lastDelayTime; + ms -= timeDiff; + + if (ms > 0) { + Term.wait(ms); + } // else delaying further would go past the time we want to delay until + + lastDelayTime = getTime(); +} + static boolean curses_pauseForMilliseconds(short milliseconds) { Term.refresh(); - Term.wait(milliseconds); + _delayUpTo(milliseconds); // hasKey returns true if we have a mouse event, too. return Term.hasKey(); @@ -124,14 +139,11 @@ static boolean curses_pauseForMilliseconds(short milliseconds) { static void curses_nextKeyOrMouseEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsDance) { int key; // TCOD_mouse_t mouse; - uint64_t theTime, waitTime; // short x, y; Term.refresh(); for (;;) { - theTime = getTime(); //TCOD_sys_elapsed_milli(); - /*if (TCOD_console_is_window_closed()) { rogue.gameHasEnded = true; // causes the game loop to terminate quickly returnEvent->eventType = KEYSTROKE; @@ -188,11 +200,7 @@ static void curses_nextKeyOrMouseEvent(rogueEvent *returnEvent, boolean textInpu return; } - waitTime = PAUSE_BETWEEN_EVENT_POLLING + theTime - getTime(); - - if (waitTime > 0 && waitTime <= PAUSE_BETWEEN_EVENT_POLLING) { - curses_pauseForMilliseconds(waitTime); - } + _delayUpTo(PAUSE_BETWEEN_EVENT_POLLING); } } diff --git a/src/platform/sdl2-platform.c b/src/platform/sdl2-platform.c index 07602ca3..9468915a 100644 --- a/src/platform/sdl2-platform.c +++ b/src/platform/sdl2-platform.c @@ -279,10 +279,24 @@ static void _gameLoop() { SDL_Quit(); } +static long lastDelayTime = 0; + +// Like SDL_Delay, but reduces the delay if time has passed since the last delay +static void _delayUpTo(short ms) { + long curTime = SDL_GetTicks(); + long timeDiff = curTime - lastDelayTime; + ms -= timeDiff; + + if (ms > 0) { + SDL_Delay(ms); + } // else delaying further would go past the time we want to delay until + + lastDelayTime = SDL_GetTicks(); +} static boolean _pauseForMilliseconds(short ms) { updateScreen(); - SDL_Delay(ms); + _delayUpTo(ms); if (lastEvent.eventType != EVENT_ERROR && lastEvent.eventType != MOUSE_ENTERED_CELL) { @@ -296,8 +310,6 @@ static boolean _pauseForMilliseconds(short ms) { static void _nextKeyOrMouseEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsDance) { - long tstart, dt; - updateScreen(); if (lastEvent.eventType != EVENT_ERROR) { @@ -307,8 +319,6 @@ static void _nextKeyOrMouseEvent(rogueEvent *returnEvent, boolean textInput, boo } while (true) { - tstart = SDL_GetTicks(); - if (colorsDance) { shuffleTerrainColors(3, true); commitDraws(); @@ -318,10 +328,7 @@ static void _nextKeyOrMouseEvent(rogueEvent *returnEvent, boolean textInput, boo if (pollBrogueEvent(returnEvent, textInput)) break; - dt = PAUSE_BETWEEN_EVENT_POLLING - (SDL_GetTicks() - tstart); - if (dt > 0) { - SDL_Delay(dt); - } + _delayUpTo(PAUSE_BETWEEN_EVENT_POLLING); } }