summaryrefslogtreecommitdiff
path: root/src/game.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game.cpp')
-rw-r--r--src/game.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/game.cpp b/src/game.cpp
index dd038ad..74f2220 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -20,6 +20,7 @@
#include <cstring>
#include <iomanip>
#include <ostream>
+#include <thread>
const uint64_t consoleBufferCount = 30;
const uint64_t consoleLineLength = 128;
@@ -1114,6 +1115,117 @@ void RecordImGuiEditor() {
}
}
+void Game_Main(PKEWindowProperties *windowProps) {
+ fprintf(stdout, "Game_Main Entering\n");
+ try {
+ AM_Init();
+ Physics_Init();
+ Game_Init();
+ ECS_Init();
+ CreateWindow(windowProps);
+ PkeInput_Init();
+ EntityType_Init();
+
+ GameTimePoint lastTimePoint = pkeSettings.steadyClock.now();
+ double deltaTillNextRender = pkeSettings.deltaPerFrame;
+ GameTimePoint lastLogTimePoint = pkeSettings.steadyClock.now();
+ int64_t tickCount = 0;
+ int64_t renderCount = 0;
+
+ int64_t nsAhead = 0.0;
+
+ while (pkeSettings.isGameRunning) {
+
+ glfwPollEvents();
+
+ int64_t nsAheadHolder = 0.0;
+ if (nsAhead > 0) {
+ nsAheadHolder = nsAhead;
+ std::this_thread::sleep_for(GameTimeDuration(nsAhead));
+ nsAhead = 0;
+ }
+ if (vidMode.refreshRate != pkeSettings.targetFPS) {
+ pkeSettings.targetFPS = vidMode.refreshRate;
+ pkeSettings.deltaPerFrame = 1 / double(pkeSettings.targetFPS);
+ }
+
+ GameTimePoint currentTimePoint = pkeSettings.steadyClock.now();
+ double deltaThisTick = ((currentTimePoint - lastTimePoint).count() - nsAheadHolder) / NANO_DENOM_DOUBLE;
+ deltaThisTick = std::min(deltaThisTick, pkeSettings.minimumDeltaPerFrame);
+ lastTimePoint = currentTimePoint;
+
+ deltaTillNextRender -= deltaThisTick;
+ bool shouldRender = pkeSettings.graphicsSettings.isFramerateUnlocked
+ || pkeSettings.graphicsSettings.isWaitingForVsync
+ || deltaTillNextRender <= 0.0;
+
+ if (shouldRender == false && (deltaTillNextRender > 0.0 && deltaTillNextRender - (deltaThisTick * 2.0) <= 0.0)) {
+ /*
+ * We are ahead of the render schedule
+ * && the current tick's speed would put us behind schedule next tick.
+ * Simulate the extra time we are ahead and prepare to sleep the difference
+ * before the next tick.
+ */
+ nsAhead = std::floor(deltaTillNextRender * NANO_DENOM_DOUBLE);
+ deltaThisTick += deltaTillNextRender;
+ shouldRender = true;
+ }
+
+ tickCount += 1;
+ Game_Tick(deltaThisTick);
+
+ if (shouldRender) {
+ Render();
+ renderCount += 1;
+ double msBehind = deltaTillNextRender * -1000;
+ int64_t behindCount = 0;
+ while (deltaTillNextRender < pkeSettings.deltaPerFrame) {
+ behindCount += 1;
+ deltaTillNextRender += pkeSettings.deltaPerFrame;
+ }
+ if (behindCount > 2) {
+ fprintf(stderr, "[PKE::main] late render - simulated ahead: %fms - delta behind: %fms - missed frames:%ld\n", nsAheadHolder / (NANO_DENOM_DOUBLE / 1000), msBehind, behindCount - 1);
+ fflush(stderr);
+ }
+ }
+
+ if ((currentTimePoint - lastLogTimePoint).count() > std::chrono::nanoseconds::period::den) {
+ lastLogTimePoint = currentTimePoint;
+ fprintf(stdout, "TPS: ~%ld - actual:%ld - presents:%ld\n", int64_t(1 / deltaThisTick), tickCount, renderCount);
+ fflush(stdout);
+ tickCount = 0;
+ renderCount = 0;
+ }
+
+ pkeSettings.isGameRunning = !glfwWindowShouldClose(window);
+ }
+
+ vkDeviceWaitIdle(vkDevice);
+
+ } catch (const std::exception &exc) {
+ fprintf(stdout, "Game_Main EXCEPTION: %s\n", exc.what());
+ } catch (const char *err) {
+ fprintf(stdout, "Game_Main UNHANDLED EXCEPTION: %s\n", err);
+ } catch (...) {
+ fprintf(stdout, "Game_Main UNHANDLED EXCEPTION\n");
+ }
+ fprintf(stdout, "Game_Main SHUTDOWN INITIATED\n");
+#ifndef NDEBUG
+ Pke_DebugPrint();
+#endif
+ Game_Teardown();
+ Event_Teardown();
+ EntityType_Teardown();
+ PkeInput_Teardown();
+ Physics_Teardown();
+ ECS_Teardown();
+ AM_DebugPrint();
+ AM_Teardown();
+ DestroyWindow();
+ Pke_DebugPrint();
+ fprintf(stdout, "Game_Main Exiting\n");
+}
+
void Game_Init() {
pkeSettings.mem.bkt = Pke_BeginTransientBucket(1UL << 26);