summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2023-08-12 23:17:23 -0400
committerJonathan Bradley <jcb@pikum.xyz>2023-08-12 23:18:39 -0400
commitaf5d06a391aafd0c5a24cf15eeaeddbb9b4f8182 (patch)
tree059321ff6ad038aed8420a8b4c102049acf4c6d1 /src
parent427f3ca69e062facdd5d70dae583c5ee99b9bb87 (diff)
added game loop with render sync
Diffstat (limited to 'src')
-rw-r--r--src/game.hpp6
-rw-r--r--src/main.cpp61
2 files changed, 66 insertions, 1 deletions
diff --git a/src/game.hpp b/src/game.hpp
index 80c971f..4ab021b 100644
--- a/src/game.hpp
+++ b/src/game.hpp
@@ -6,13 +6,17 @@
using GameTimeDuration = std::chrono::duration<int64_t, std::nano>;
using GameTimePoint = std::chrono::steady_clock::time_point;
+#define NANO_DENOM std::chrono::nanoseconds::period::den
+#define NANO_DENOM_DOUBLE double(std::chrono::nanoseconds::period::den)
struct GameSettings {
bool isGameRunning = true;
bool isGamePaused = false;
bool isFramerateUnlocked = true;
int64_t targetFPS = 144;
- GameTimeDuration nanosecondsPerFrame = GameTimeDuration(std::chrono::nanoseconds::period::den / targetFPS);
+ int64_t minFPS = 20;
+ double deltaPerFrame = 1 / double(targetFPS);
+ double minimumDeltaPerFrame = 1 / double(minFPS);
};
extern GameSettings pkeSettings;
diff --git a/src/main.cpp b/src/main.cpp
index be70826..b1c33aa 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,17 +1,78 @@
+#include <chrono>
#include <cstdio>
+#include <cmath>
#include <exception>
+#include <thread>
#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 (...) {