#include #include #include #include #include #include "asset-manager.hpp" #include "game.hpp" #include "window.hpp" PKEWindowProperties windowProps{}; void Tick(double delta) { /* no-op */ } int main() { printf("PKE ENTERING\n"); try { AssetManagerInit(); CreateWindow(&windowProps); auto steadyClock = std::chrono::steady_clock(); GameTimePoint lastTimePoint = steadyClock.now(); double deltaTillNextRender = pkeSettings.deltaPerFrame; GameTimePoint lastLogTimePoint = steadyClock.now(); int64_t tickCount = 0; int64_t nsAhead = 0.0; while (pkeSettings.isGameRunning) { if (nsAhead > 0) { std::this_thread::sleep_until(lastTimePoint + GameTimeDuration(nsAhead + 1)); nsAhead = 0; } GameTimePoint currentTimePoint = steadyClock.now(); double deltaThisTick = (currentTimePoint - lastTimePoint).count() / NANO_DENOM_DOUBLE; deltaThisTick = std::min(deltaThisTick, pkeSettings.minimumDeltaPerFrame); deltaTillNextRender -= deltaThisTick; bool shouldRender = deltaTillNextRender < deltaThisTick; lastTimePoint = currentTimePoint; if (shouldRender) { if (deltaTillNextRender > 0.0 && deltaThisTick < pkeSettings.deltaPerFrame) { /* * We are ahead of schedule && the current tick is faster than our target FPS. * Simulate the extra time we are ahead and prepare to sleep the difference * before the next tick. */ nsAhead = std::ceil(deltaTillNextRender * NANO_DENOM_DOUBLE); deltaThisTick += deltaTillNextRender; } deltaTillNextRender += pkeSettings.deltaPerFrame; } tickCount += 1; Tick(deltaThisTick); if (shouldRender) { PreRender(); Render(); PostRender(); } if (shouldRender == false && (currentTimePoint - lastLogTimePoint).count() > std::chrono::nanoseconds::period::den) { lastLogTimePoint = currentTimePoint; printf("TPS: ~%ld - actual:%ld\n", int64_t(1 / deltaThisTick), tickCount); tickCount = 0; } } } catch (const std::exception &exc) { printf("EXCEPTION: %s\n", exc.what()); } catch (...) { printf("UNHANDLED EXCEPTION\n"); } DestroyWindow(); printf("PKE EXITING\n"); return 0; }