mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-01-17 22:38:38 +01:00
Cap FPS in a more stable way
Time-related variables are now on the nanosecond scale. See #886.
This commit is contained in:
parent
225293cc80
commit
c6d6a7d0bf
@ -5,6 +5,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <cstdint>
|
||||||
#ifdef WIN
|
#ifdef WIN
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#endif
|
#endif
|
||||||
@ -298,8 +299,8 @@ unsigned int GetTicks()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int elapsedTime = 0, currentTime = 0, lastTime = 0, currentFrame = 0;
|
int elapsedTime = 0, currentTime = 0, lastTime = 0, currentFrame = 0;
|
||||||
unsigned int lastTick = 0;
|
uint64_t lastTick = 0;
|
||||||
unsigned int lastFpsUpdate = 0;
|
uint64_t lastFpsUpdate = 0;
|
||||||
float fps = 0;
|
float fps = 0;
|
||||||
ui::Engine * engine = NULL;
|
ui::Engine * engine = NULL;
|
||||||
bool showLargeScreenDialog = false;
|
bool showLargeScreenDialog = false;
|
||||||
@ -467,18 +468,14 @@ void LargeScreenDialog()
|
|||||||
|
|
||||||
void EngineProcess()
|
void EngineProcess()
|
||||||
{
|
{
|
||||||
double frameTimeAvg = 0.0f, correctedFrameTimeAvg = 0.0f;
|
double correctedFrameTimeAvg = 0;
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
||||||
int drawingTimer = 0;
|
uint64_t drawingTimer = 0;
|
||||||
int frameStart = 0;
|
auto frameStart = uint64_t(SDL_GetTicks()) * UINT64_C(1'000'000);
|
||||||
|
|
||||||
while(engine->Running())
|
while(engine->Running())
|
||||||
{
|
{
|
||||||
int oldFrameStart = frameStart;
|
|
||||||
frameStart = SDL_GetTicks();
|
|
||||||
drawingTimer += frameStart - oldFrameStart;
|
|
||||||
|
|
||||||
if(engine->Broken()) { engine->UnBreak(); break; }
|
if(engine->Broken()) { engine->UnBreak(); break; }
|
||||||
event.type = 0;
|
event.type = 0;
|
||||||
while (SDL_PollEvent(&event))
|
while (SDL_PollEvent(&event))
|
||||||
@ -491,7 +488,7 @@ void EngineProcess()
|
|||||||
engine->Tick();
|
engine->Tick();
|
||||||
|
|
||||||
int drawcap = ui::Engine::Ref().GetDrawingFrequencyLimit();
|
int drawcap = ui::Engine::Ref().GetDrawingFrequencyLimit();
|
||||||
if (!drawcap || drawingTimer > 1000.f/drawcap)
|
if (!drawcap || drawingTimer > 1e9f / drawcap)
|
||||||
{
|
{
|
||||||
engine->Draw();
|
engine->Draw();
|
||||||
drawingTimer = 0;
|
drawingTimer = 0;
|
||||||
@ -506,24 +503,27 @@ void EngineProcess()
|
|||||||
|
|
||||||
blit(engine->g->vid);
|
blit(engine->g->vid);
|
||||||
}
|
}
|
||||||
|
auto fpsLimit = ui::Engine::Ref().FpsLimit;
|
||||||
int frameTime = SDL_GetTicks() - frameStart;
|
auto now = uint64_t(SDL_GetTicks()) * UINT64_C(1'000'000);
|
||||||
frameTimeAvg = frameTimeAvg * 0.8 + frameTime * 0.2;
|
auto oldFrameStart = frameStart;
|
||||||
float fpsLimit = ui::Engine::Ref().FpsLimit;
|
frameStart = now;
|
||||||
if (fpsLimit > 2)
|
if (fpsLimit > 2)
|
||||||
{
|
{
|
||||||
double offset = 1000.0 / fpsLimit - frameTimeAvg;
|
auto timeBlockDuration = uint64_t(UINT64_C(1'000'000'000) / fpsLimit);
|
||||||
if(offset > 0)
|
auto oldFrameStartTimeBlock = oldFrameStart / timeBlockDuration;
|
||||||
SDL_Delay(Uint32(offset + 0.5));
|
auto frameStartTimeBlock = oldFrameStartTimeBlock + 1U;
|
||||||
|
frameStart = std::max(frameStart, frameStartTimeBlock * timeBlockDuration);
|
||||||
|
SDL_Delay((frameStart - now) / UINT64_C(1'000'000));
|
||||||
}
|
}
|
||||||
int correctedFrameTime = SDL_GetTicks() - frameStart;
|
auto correctedFrameTime = frameStart - oldFrameStart;
|
||||||
correctedFrameTimeAvg = correctedFrameTimeAvg * 0.95 + correctedFrameTime * 0.05;
|
drawingTimer += correctedFrameTime;
|
||||||
if (frameStart - lastFpsUpdate > 200)
|
correctedFrameTimeAvg = correctedFrameTimeAvg + (correctedFrameTime - correctedFrameTimeAvg) * 0.05;
|
||||||
|
if (frameStart - lastFpsUpdate > UINT64_C(200'000'000))
|
||||||
{
|
{
|
||||||
engine->SetFps(1000.0 / correctedFrameTimeAvg);
|
engine->SetFps(1e9f / correctedFrameTimeAvg);
|
||||||
lastFpsUpdate = frameStart;
|
lastFpsUpdate = frameStart;
|
||||||
}
|
}
|
||||||
if (frameStart - lastTick > 100)
|
if (frameStart - lastTick > UINT64_C(100'000'000))
|
||||||
{
|
{
|
||||||
lastTick = frameStart;
|
lastTick = frameStart;
|
||||||
Client::Ref().Tick();
|
Client::Ref().Tick();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user