3#include <Logger/Logger.hpp>
9#include "EngineContext.hpp"
11#include "events/busEvents.hpp"
25 using Clock = std::chrono::steady_clock;
34 ecs::Registry &
registry() {
return _registry; }
51 void stop() { _running =
false; }
57 void setFPS(uint32_t fps) { _targetFps = fps; }
70 template <Game TGame>
int run(TGame &game) {
72 .registry = _registry,
73 .scheduler = _scheduler,
74 .eventBus = _eventBus,
80 auto currentTime = Clock::now();
81 auto nextFrameTarget = currentTime;
83 float accumulator = 0.0f;
84 const float fixedDeltaTime = 1.0f / 60.0f;
86 _scheduler.start(_registry);
90 if constexpr (
requires {
91 { game.shouldContinue() } -> std::convertible_to<bool>;
93 if (!game.shouldContinue())
97 auto newTime = Clock::now();
99 std::chrono::duration<float>(newTime - currentTime).count();
100 currentTime = newTime;
102 float frameTime = std::min(realDeltaTime, 0.25f);
103 accumulator += frameTime;
105 while (accumulator >= fixedDeltaTime) {
106 accumulator -= fixedDeltaTime;
109 if constexpr (
requires {
111 game.onUpdate(context, frameTime)
112 } -> std::same_as<void>;
114 game.onUpdate(context, frameTime);
116 _scheduler.run(_registry, frameTime);
119 updateFPS(realDeltaTime);
121 if (_targetFps > 0) {
122 const auto targetDuration =
123 std::chrono::nanoseconds(1000000000 / _targetFps);
125 nextFrameTarget += targetDuration;
127 auto sleepStart = Clock::now();
129 if (nextFrameTarget > sleepStart) {
130 auto timeToSleep = nextFrameTarget - sleepStart;
132 if (timeToSleep > std::chrono::milliseconds(2))
133 std::this_thread::sleep_for(timeToSleep -
134 std::chrono::milliseconds(2));
136 while (Clock::now() < nextFrameTarget) {
139 nextFrameTarget = Clock::now();
144 _scheduler.stop(_registry);
148 _scheduler.stop(_registry);
149 if constexpr (
requires { game.onUnload(context); }) {
150 game.onUnload(context);
156 void updateFPS(
float realDeltaTime) {
157 _fpsTimer += realDeltaTime;
159 if (_fpsTimer >= 1.0f) {
160 LOG_DEBUG(
"FPS: " + std::to_string(_fpsFrames));
166 ecs::Registry _registry;
167 ecs::Scheduler _scheduler;
170 bool _running =
false;
171 uint32_t _targetFps = 0;
173 float _fpsTimer = 0.0f;
Type indexed publish and subscribe event bus.
Definition busEvents.hpp:20
Owns the ECS world and runs the main loop of a game.
Definition GameEngine.hpp:22
void stop()
Asks the main loop to exit after the current frame.
Definition GameEngine.hpp:51
void setFPS(uint32_t fps)
Sets the frame rate cap.
Definition GameEngine.hpp:57
busEvent & eventBus()
Returns the event bus shared by the systems.
Definition GameEngine.hpp:46
ecs::Scheduler & scheduler()
Returns the system scheduler.
Definition GameEngine.hpp:40
int run(TGame &game)
Loads the game and runs frames until it stops.
Definition GameEngine.hpp:70
ecs::Registry & registry()
Returns the entity and component registry.
Definition GameEngine.hpp:34
std::chrono::steady_clock Clock
Monotonic clock used to measure frame times.
Definition GameEngine.hpp:25
Engine services handed to the game and its scenes.
Definition EngineContext.hpp:20