Skip to main content

GameLoop Class

Central orchestrator for the game update cycle. More...

Declaration

class helios::engine::runtime::gameloop::GameLoop { ... }

Base class

classPassCommitListener

Interface for receiving notifications when a pass reaches its commit point. More...

Public Constructors Index

GameLoop ()=default

Default constructor. More...

Public Member Functions Index

helios::engine::runtime::gameloop::Phase &phase (const helios::engine::runtime::gameloop::PhaseType phaseType) noexcept

Returns a reference to the specified phase. More...

voidinit (GameWorld &gameWorld)

Initializes the GameLoop and all registered phases and passes. More...

voidupdate (GameWorld &gameWorld, float deltaTime, const helios::input::InputSnapshot &inputSnapshot, std::span< const helios::rendering::ViewportSnapshot > viewportSnapshots) noexcept

Executes one full frame update across all phases. More...

Protected Member Functions Index

voidonPassCommit (const CommitPoint commitPoint, GameWorld &gameWorld, UpdateContext &updateContext) noexcept override

Commits pass-level state based on the specified CommitPoint flags. More...

voidphaseCommit (GameWorld &gameWorld, UpdateContext &updateContext)

Commits phase-level events and flushes commands and managers. More...

Protected Member Attributes Index

helios::engine::runtime::gameloop::PhaseprePhase_ {*this}

The pre-update phase, executed before main gameplay logic. More...

helios::engine::runtime::gameloop::PhasemainPhase_ {*this}

The main update phase for core gameplay systems. More...

helios::engine::runtime::gameloop::PhasepostPhase_ {*this}

The post-update phase for cleanup and synchronization. More...

helios::engine::runtime::messaging::event::GameLoopEventBusphaseEventBus_ {}

Event bus for phase-level event propagation. More...

helios::engine::runtime::messaging::event::GameLoopEventBuspassEventBus_ {}

Event bus for pass-level event propagation. More...

helios::engine::runtime::messaging::event::GameLoopEventBusframeEventBus_ {}

Event bus for frame-level event propagation. More...

floattotalTime_ = 0.0f

Accumulated total time since the first frame, in seconds. More...

Private Member Attributes Index

boolinitialized_ = false

Flag indicating whether init() has been called. More...

Protected Static Attributes Index

static const helios::util::log::Logger &logger_ = ...

The logger used with this GameLoop instance. More...

Description

Central orchestrator for the game update cycle.

The GameLoop manages the execution of game systems across three distinct phases: Pre, Main, and Post. Each phase can contain multiple passes, and each pass can have a configurable commit point for fine-grained synchronization control.

## Ownership

The GameLoop owns:

  • **Three phases** (Pre, Main, Post), each containing passes with registered systems.
  • **Three event buses** for different propagation scopes:
    • `phaseEventBus_`: Events readable in the next phase.
    • `passEventBus_`: Events readable in subsequent passes (within the same phase).
    • `frameEventBus_`: Events readable in the next frame.

The EngineCommandBuffer and Managers are owned by the GameWorld's ResourceRegistry and accessed via UpdateContext during commit points.

## Commit Points

Commit points allow systems to specify when commands should be flushed, managers should process their requests, and pass-level events should be synchronized. This enables deterministic ordering and fine-grained control over the update cycle.

## Frame Lifecycle

``` ┌─────────────────────────────────────────────────────────────┐ │ FRAME N │ ├─────────────────┬─────────────────┬─────────────────────────┤ │ PRE PHASE │ MAIN PHASE │ POST PHASE │ │ (Input, Cmd) │ (Physics, AI) │ (Cleanup, Sync) │ ├─────────────────┼─────────────────┼─────────────────────────┤ │ phaseCommit()phaseCommit()phaseCommit() │ │ │ │ frameEventBus_.swap() │ └─────────────────┴─────────────────┴─────────────────────────┘ ```

See Also

Phase

See Also

Pass

See Also

CommitPoint

See Also

ResourceRegistry

See Also

EngineCommandBuffer

See Also

PassCommitListener

Definition at line 94 of file GameLoop.ixx.

Public Constructors

GameLoop()

helios::engine::runtime::gameloop::GameLoop::GameLoop ()
default

Default constructor.

Creates a GameLoop with empty phases. Systems must be added to the phases via `phase(PhaseType).addPass().addSystem<T>()` before calling `init()`.

Definition at line 266 of file GameLoop.ixx.

Public Member Functions

init()

void helios::engine::runtime::gameloop::GameLoop::init (GameWorld & gameWorld)
inline

Initializes the GameLoop and all registered phases and passes.

Iterates through all phases (Pre, Main, Post) and calls their `init()` methods, which in turn initialize all registered passes and systems. Systems receive a reference to the GameWorld for component queries and entity access.

Must be called exactly once before the first `update()` call.

Parameters
gameWorld

Reference to the game world to initialize with.

Precondition

Must not have been called before (asserts on multiple calls).

See Also

Phase::init()

See Also

Pass::init()

See Also

System::init()

Definition at line 312 of file GameLoop.ixx.

312 void init(GameWorld& gameWorld) {
313
314 assert(!initialized_ && "init() already called");
315
319 switch (phase) {
321 prePhase_.init(gameWorld);
322 prePhase_.addPassCommitListener(this);
323 break;
325 mainPhase_.init(gameWorld);
326 mainPhase_.addPassCommitListener(this);
327 break;
329 postPhase_.init(gameWorld);
330 postPhase_.addPassCommitListener(this);
331 break;
332 }
333 }
334
335 initialized_ = true;
336 }

References helios::engine::runtime::gameloop::Main, mainPhase_, phase, helios::engine::runtime::gameloop::Post, postPhase_, helios::engine::runtime::gameloop::Pre and prePhase_.

phase()

helios::engine::runtime::gameloop::Phase & helios::engine::runtime::gameloop::GameLoop::phase (const helios::engine::runtime::gameloop::PhaseType phaseType)
inline nodiscard noexcept

Returns a reference to the specified phase.

Parameters
phaseType

The type of phase to retrieve (Pre, Main, or Post).

Returns

Reference to the requested Phase.

Definition at line 275 of file GameLoop.ixx.

276
277 switch (phaseType) {
279 return prePhase_;
280 break;
282 return mainPhase_;
283 break;
285 return postPhase_;
286 break;
287 }
288
289 std::unreachable();
290
291 }

References helios::engine::runtime::gameloop::Main, mainPhase_, helios::engine::runtime::gameloop::Post, postPhase_, helios::engine::runtime::gameloop::Pre and prePhase_.

Referenced by init and update.

update()

void helios::engine::runtime::gameloop::GameLoop::update (GameWorld & gameWorld, float deltaTime, const helios::input::InputSnapshot & inputSnapshot, std::span< const helios::rendering::ViewportSnapshot > viewportSnapshots)
inline noexcept

Executes one full frame update across all phases.

Iterates through Pre, Main, and Post phases, updating all registered systems and committing events and commands after each phase. The frame lifecycle:

1. **Pre Phase:** Input processing, command generation, preparation 2. **Main Phase:** Core gameplay logic, physics, collision detection 3. **Post Phase:** Cleanup, synchronization, rendering preparation

After each phase, `phaseCommit()` is called to:

  • Swap phase event buffers (events become readable in next phase)
  • Clear pass event buffers
  • Flush command buffer
  • Flush managers

After the Post phase, the frame event bus is swapped, making frame-level events readable in the next frame.

Parameters
gameWorld

Reference to the game world.

deltaTime

Time elapsed since the last frame in seconds.

inputSnapshot

Snapshot of the current input state.

viewportSnapshots

Snapshots of viewports registered with an id.

Precondition

init() must have been called before the first update.

See Also

Phase

See Also

phaseCommit()

See Also

UpdateContext

Definition at line 368 of file GameLoop.ixx.

368 void update(
369 GameWorld& gameWorld,
370 float deltaTime,
371 const helios::input::InputSnapshot& inputSnapshot,
372 std::span<const helios::rendering::ViewportSnapshot> viewportSnapshots
373 ) noexcept {
374
375 assert(initialized_ && "GameLoop not initialized");
376
377 totalTime_ += deltaTime;
378
379 auto updateContext = UpdateContext(
380 gameWorld.resourceRegistry(),
381 helios::engine::ecs::EntityResolver(&gameWorld.entityManager()),
382 gameWorld.session(),
383 deltaTime,
388 inputSnapshot,
389 viewportSnapshots,
390 gameWorld.level()
391 );
392
393 auto& session = gameWorld.session();
394
395 // gameloop phases
399
400 switch (phase) {
402 prePhase_.update(gameWorld, updateContext);
403 phaseCommit(gameWorld, updateContext);
404
405 break;
407 mainPhase_.update(gameWorld, updateContext);
408 phaseCommit(gameWorld, updateContext);
409
410 break;
412 postPhase_.update(gameWorld, updateContext);
413 phaseCommit(gameWorld, updateContext);
414 frameEventBus_.swapBuffers();
415 break;
416 }
417
418
419 }
420 }

References frameEventBus_, helios::engine::runtime::gameloop::Main, mainPhase_, passEventBus_, phase, phaseCommit, phaseEventBus_, helios::engine::runtime::gameloop::Post, postPhase_, helios::engine::runtime::gameloop::Pre, prePhase_ and totalTime_.

Protected Member Functions

onPassCommit()

void helios::engine::runtime::gameloop::GameLoop::onPassCommit (const CommitPoint commitPoint, GameWorld & gameWorld, UpdateContext & updateContext)
inline noexcept protected virtual

Commits pass-level state based on the specified CommitPoint flags.

Called after each pass that has a commit point configured. The CommitPoint flags determine which synchronization actions are performed:

  • **PassEvents:** Swaps pass event bus buffers, making events pushed via `UpdateContext::pushPass()` readable in subsequent passes.
  • **FlushCommands:** Executes pending commands from the CommandBuffer.
  • **FlushManagers:** Processes manager requests (e.g., spawning from pools).

The order is: FlushCommands → FlushManagers → PassEvents. Commands must be flushed before managers to ensure spawn requests are generated before being processed.

Parameters
commitPoint

The flags specifying which actions to perform.

gameWorld

The game world where the commit occured.

updateContext

The current update context.

See Also

CommitPoint

See Also

Pass::addCommitPoint()

See Also

UpdateContext::pushPass()

See Also

UpdateContext::readPass()

Definition at line 202 of file GameLoop.ixx.

203 const CommitPoint commitPoint,
204 GameWorld& gameWorld,
205 UpdateContext& updateContext) noexcept override {
206
207 // commands must be executed before Managers
209 gameWorld.flushCommandBuffers(updateContext);
210 }
211
213 gameWorld.flushManagers(updateContext);
214 }
215
216 // managers might create pass events
217 if ((commitPoint & CommitPoint::PassEvents) == CommitPoint::PassEvents) {
218 passEventBus_.swapBuffers();
219 }
220
221 }

References helios::engine::runtime::gameloop::FlushCommands, helios::engine::runtime::gameloop::FlushManagers, passEventBus_ and helios::engine::runtime::gameloop::PassEvents.

phaseCommit()

void helios::engine::runtime::gameloop::GameLoop::phaseCommit (GameWorld & gameWorld, UpdateContext & updateContext)
inline protected

Commits phase-level events and flushes commands and managers.

Called after each phase completes. This method:

1. Clears pass event buffers for the new phase. 2. Flushes the command buffer, executing deferred commands. 3. Flushes managers, allowing to process any request generated by the commands. 4. Swaps phase event bus buffers, making events readable in the next phase.

Parameters
gameWorld

Reference to the game world.

updateContext

The current update context.

See Also

UpdateContext::pushPhase()

See Also

UpdateContext::readPhase()

Definition at line 239 of file GameLoop.ixx.

240 GameWorld& gameWorld,
241 UpdateContext& updateContext) {
242
243 passEventBus_.clearAll();
244
245 // command buffers generate requests for managers, so this comes first
246 gameWorld.flushCommandBuffers(updateContext);
247
248 // managers process requests
249 gameWorld.flushManagers(updateContext);
250
251 // make sure flushed managers make their events available to the phase event bus
252 phaseEventBus_.swapBuffers();
253 }

References helios::engine::runtime::world::GameWorld::flushCommandBuffers, helios::engine::runtime::world::GameWorld::flushManagers, passEventBus_ and phaseEventBus_.

Referenced by update.

Protected Member Attributes

frameEventBus_

helios::engine::runtime::messaging::event::GameLoopEventBus helios::engine::runtime::gameloop::GameLoop::frameEventBus_ {}
protected

Event bus for frame-level event propagation.

Events pushed via `UpdateContext::pushFrame()` are buffered here and become readable in the next frame via `UpdateContext::readFrame()`. The buffer swap occurs at the end of the Post phase.

Frame-level events persist across all phases within a frame and are useful for cross-frame communication (e.g., collision events that should be processed in the next frame).

See Also

UpdateContext::pushFrame()

See Also

UpdateContext::readFrame()

Definition at line 170 of file GameLoop.ixx.

Referenced by update.

mainPhase_

helios::engine::runtime::gameloop::Phase helios::engine::runtime::gameloop::GameLoop::mainPhase_ {*this}
protected

The main update phase for core gameplay systems.

Definition at line 123 of file GameLoop.ixx.

Referenced by init, phase and update.

passEventBus_

helios::engine::runtime::messaging::event::GameLoopEventBus helios::engine::runtime::gameloop::GameLoop::passEventBus_ {}
protected

Event bus for pass-level event propagation.

Events pushed via `UpdateContext::pushPass()` are buffered here and become readable in subsequent passes via `UpdateContext::readPass()`. The buffer swap occurs when a pass has a commit point.

See Also

UpdateContext::pushPass()

See Also

UpdateContext::readPass()

See Also

Pass::addCommitPoint()

Definition at line 154 of file GameLoop.ixx.

Referenced by onPassCommit, phaseCommit and update.

phaseEventBus_

helios::engine::runtime::messaging::event::GameLoopEventBus helios::engine::runtime::gameloop::GameLoop::phaseEventBus_ {}
protected

Event bus for phase-level event propagation.

Events pushed via `UpdateContext::pushPhase()` are buffered here and become readable in the next phase via `UpdateContext::readPhase()`. The buffer swap occurs in phaseCommit().

See Also

UpdateContext::pushPhase()

See Also

UpdateContext::readPhase()

Definition at line 141 of file GameLoop.ixx.

Referenced by phaseCommit and update.

postPhase_

helios::engine::runtime::gameloop::Phase helios::engine::runtime::gameloop::GameLoop::postPhase_ {*this}
protected

The post-update phase for cleanup and synchronization.

Definition at line 128 of file GameLoop.ixx.

Referenced by init, phase and update.

prePhase_

helios::engine::runtime::gameloop::Phase helios::engine::runtime::gameloop::GameLoop::prePhase_ {*this}
protected

The pre-update phase, executed before main gameplay logic.

Definition at line 118 of file GameLoop.ixx.

Referenced by init, phase and update.

totalTime_

float helios::engine::runtime::gameloop::GameLoop::totalTime_ = 0.0f
protected

Accumulated total time since the first frame, in seconds.

Definition at line 175 of file GameLoop.ixx.

175 float totalTime_ = 0.0f;

Referenced by update.

Private Member Attributes

initialized_

bool helios::engine::runtime::gameloop::GameLoop::initialized_ = false

Flag indicating whether init() has been called.

Used to assert that init() is called exactly once before the first update() and to prevent multiple initializations.

Definition at line 103 of file GameLoop.ixx.

103 bool initialized_ = false;

Protected Static Attributes

logger_

const helios::util::log::Logger& helios::engine::runtime::gameloop::GameLoop::logger_
protected static

The logger used with this GameLoop instance.

Initialiser

Definition at line 111 of file GameLoop.ixx.


The documentation for this class was generated from the following file:


Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.