#include #include #include #include #include #include #include "asset-manager.hpp" #include "ecs.hpp" #include "game.hpp" #include "window.hpp" #include "entities.hpp" void signal_handler(int signal_num) { printf("Received signal: %d - shutting down\n", signal_num); pkeSettings.isGameRunning = false; } PKEWindowProperties windowProps{}; void Tick(double delta) { Game_Tick(delta); } int main() { signal(SIGTERM, signal_handler); printf("PKE ENTERING\n"); try { AM_Init(); Game_Init(); ECS_Init(); CreateWindow(&windowProps); EntityType_Init(); 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) { glfwPollEvents(); 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) { Render(); } 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; } pkeSettings.isGameRunning = !glfwWindowShouldClose(window); } vkDeviceWaitIdle(vkDevice); } catch (const std::exception &exc) { printf("EXCEPTION: %s\n", exc.what()); } catch (const char *err) { printf("UNHANDLED EXCEPTION: %s\n", err); } catch (...) { printf("UNHANDLED EXCEPTION\n"); } printf("PKE SHUTDOWN INITIATED\n"); EntityType_Teardown(); DestroyWindow(); printf("PKE EXITING\n"); return 0; }