1. Dashboard
  2. Getting Started
  3. GitHub
  4. API
  5. Articles
  6. Level Editor
  7. Members
    1. Recent Activity
    2. Users Online
    3. Staff
    4. Search Members
  8. Forum
  9. Discord
  • Login
  • Register
  • Search
Getting Started
  • Everywhere
  • Getting Started
  • Articles
  • Pages
  • Forum
  • More Options
  1. GFX-Engine
  2. Articles
  3. Getting Started

Application Structure & Game Loop

  • Andy
  • January 4, 2026 at 10:02 AM
  • 265 Views
  • 0 Comments

This article describes how a GFX-Next application is structured and how the game loop is executed. It breaks down the overall application layout, including initialization, system setup, and shutdown, and explains how these phases relate to the lifetime of

Contents [hideshow]
  1. The Game Class
  2. Application Lifecycle Overview
  3. LoadContent: Asset Definition Phase
  4. Asset Initialization Phase
  5. Initialize: Scene & System Setup
  6. OnStart: Final Setup Hook
  7. The Game Loop
  8. Update Phase
  9. Render Phase
  10. Frame-End
  11. Timing & Frame Control
  12. Shutdown & Disposal
  13. Summary

The design focuses on:

  • explicit control flow
  • predictable timing
  • clear separation of responsibilities
  • identical behavior in runtime and editor

1. The Game Class

Every application using GFX-Next derives from the Game base class.

C#
public class MyGame : Game
{
}

The Game class:

  • owns the window
  • owns the render device
  • owns the asset manager
  • defines the application lifecycle
  • controls the main loop

It is intentionally thin and non-magical.


2. Application Lifecycle Overview

A typical application follows this order:

  1. Create window & render device
  2. Load assets
  3. Initialize GPU resources
  4. Initialize scene and systems
  5. Enter main loop
  6. Shutdown and dispose resources

This lifecycle is explicit and fully controlled by the user.


3. LoadContent: Asset Definition Phase

The LoadContent function allows you to load assets from the file system into the AssetManager. The AssetManager owns the assets and manages their lifetime and resources. Each asset should be handed over to the AssetManager. It also caches resources, meaning you do not need to load the same asset twice.

C#
public override void LoadContent(AssetManager assets)
{
    _cubeMesh = assets.Add<Mesh>("CubeMesh", Cube.GetMesh(material));
    _model = assets.Load<StaticMeshModel>("model.gltf");
}

4. Asset Initialization Phase

The asset initialisation is happening within the game class itself. You won't do this yourself. However, this will show you what happens. Firstly, the AssetManager uploads all the CPU data from memory to the graphics device memory. This could be vertex data or texture data, for example. After uploading to the GPU memory, the CPU resources for the assets will be freed. This function is enabled by default. However, you can disable it using the FreeCPUResources property in your game class. Set this property to false to prevent the CPU memory from being freed. However, in most cases, you will want to free the CPU memory.

After LoadContent, GPU resources are created:

C#
AssetManager.InitializeAssets(RenderDevice);

Optionally, CPU-side data may be freed:

C#
AssetManager.FreeCPUResources();

5. Initialize: Scene & System Setup

Once the assets have been loaded into the GPU and are ready for use, you can initialise your game state in the 'Initialise' function. For example, this is the perfect place to call the Scene.Init() function. This ensures that all assets are ready for use.

C#
public override void Initialize(IRenderDevice renderer)
{
    Scene.Init(Viewport, renderer);
    HUD.Init(renderer);
}

No assets should be created here.


6. OnStart: Final Setup Hook

The OnStart function is the final opportunity to perform actions before the loop begins. This function is usually unused, but if you need to perform an action after initialisation, this is where you should do it.

C#
public override void OnStart()
{
}

Typical use cases:

  • start animations
  • perform sanity checks

7. The Game Loop

The main loop is fully explicit and is also called within the game class. It looks like this:

C#
while (!Window.RequestClose())
{
    Window.ProcessEvents();

    Update(deltaTime);
    Render();

    RenderDevice.SwapBuffers();
}

There is:

  • no hidden scheduler
  • no task graph
  • no implicit frame management

8. Update Phase

The update function allows you to manage the logic of your scenes. When you call the update function from your scene, all game elements and their associated behaviours are updated too.

C#
public override void Update(float deltaTime)
{
    Scene.UpdatePhysics(deltaTime);
    Scene.Update(deltaTime);
}

Responsibilities:

  • gameplay logic
  • physics simulation
  • input handling
  • state changes

Important:
Scene structure must not be modified directly here
→ use the enqueue system.


9. Render Phase

In the render function, you can render the shadow pass and the scene itself, as well as the HUD and other elements, onto render targets. If you call the render function from the scene, all visible game elements will be rendered as well. As with the Update function, any attached behaviours will also call the Render function.

C#
public override void Render()
{
    Scene.RenderShadowMaps(Viewport, RenderDevice, Camera);
    Scene.Render(Viewport, RenderDevice, Camera);
}

Responsibilities:

  • shadow pass
  • scene rendering
  • post processing
  • UI rendering

Rendering does not mutate game state.


10. Frame-End

The frame end function is called once the update and render functions have finished. This allows you to perform certain actions at the end of each frame. It is the perfect place to call Scene.EnqueElements(), which adds elements to the scene graph.

C#
public override void OnFrameEnd()
{
    Scene.EnqueElements();
}

This phase:

  • applies enqueued scene changes
  • synchronizes physics and rendering
  • finalizes the frame state

This guarantees a clean starting state for the next frame.


11. Timing & Frame Control

The delta time is computed explicitly within the main loop of the Game class. You won't need to calculate this yourself.

C#
float deltaTime = (float)(currentTime - lastTime);

GFX-Next does not enforce:

  • fixed timestep
  • variable timestep
  • vsync policy

These decisions are left to the application.


12. Shutdown & Disposal

When the loop exits, the Game class will execute the following functions, which clean up the resources in the graphics device.

C#
AssetManager.DisposeAssets(RenderDevice);
AssetManager.ClearAssets();
RenderDevice.Dispose();

Summary

The application structure in GFX-Next is built around:

  • a minimal Game base class
  • explicit lifecycle phases
  • user-controlled game loop
  • strict separation of concerns
  • deterministic execution order

This design favors clarity and control over convenience.

  • Previous Article Rendering Pipeline & Post Processing
  • Next Article Complete Example: Minimal Game Class

Categories

  1. Advanced Tutorial 1
  2. Getting Started 8
  3. Default Category 1
  4. Reset Filter

Partner & Supporter

  1. Privacy Policy
  2. Legal Notice
Powered by WoltLab Suite™