Open-Source C++ Game Engines: Physics, Networking & Architecture

For systems engineers and game developers, studying open-source C++ game codebases provides an unparalleled masterclass in real-time computing. Unlike business microservices that tolerate garbage collection pauses and asynchronous event delays, video game engines operate under unforgiving hardware constraints: rendering 60 to 144 frames per second with frame budgets as tight as 6.94 milliseconds, simulating rigid-body physics, and synchronizing distributed multiplayer states over lossy UDP networks. Legendary open-source projects—including Godot Engine, Battle for Wesnoth, 0 A.D., Teeworlds, and OpenTTD—demonstrate how systems software must be architected for maximum memory locality, deterministic simulation, and low-latency networking. Below is an architectural exploration of the core subsystems underpinning open-source C++ game engines: the fixed-timestep simulation loop, collision response solvers (Box2D & Bullet), and reliable UDP networking protocols.

1. The Engine Heartbeat: Fixed Timestep vs. Variable Delta Time

The foundational component of any game engine is the Main Game Loop. Early games tied game speed directly to CPU clock cycles, causing games to run at uncontrollable speeds on newer hardware. A naive modern solution scales physics by elapsed frame time (dt = current_time - previous_time):

// ANTI-PATTERN: Variable Delta Time Physics
void update(float dt) {
    position += velocity * dt;
    // Non-deterministic! Variable dt causes physics tunneling and drift.
}

In high-fidelity physics simulations and networked multiplayer, variable delta time is fatal: floating-point non-determinism causes physics simulations to diverge across different hardware. Professional engines decouple physics simulation ticks from graphical rendering using an accumulator loop with a fixed timestep (e.g., 60Hz or dt = 1/60s), interpolating visual transforms between states during render calls:

// High-Performance C++20 Fixed Timestep Game Loop
#include <chrono>

void runGameLoop() {
    using clock = std::chrono::steady_clock;
    using duration = std::chrono::duration<double>;

    constexpr double FIXED_DT = 1.0 / 60.0; // 60 Hz physics tick
    auto previousTime = clock::now();
    double accumulator = 0.0;

    while (isRunning) {
        auto currentTime = clock::now();
        duration frameTime = currentTime - previousTime;
        previousTime = currentTime;

        // Clamp frameTime to avoid "Spiral of Death" on lag spikes
        accumulator += std::min(frameTime.count(), 0.25);

        // Consume accumulator in discrete fixed increments
        while (accumulator >= FIXED_DT) {
            pollInput();
            simulatePhysics(FIXED_DT);
            updateGameLogic(FIXED_DT);
            accumulator -= FIXED_DT;
        }

        // Render with linear interpolation alpha: [0.0, 1.0]
        double alpha = accumulator / FIXED_DT;
        renderScene(alpha);
    }
}

2. Physics Engines: Rigid-Body Dynamics & Spatial Partitioning

Studying physics libraries like Box2D (2D) and Bullet Physics (3D) reveals how mathematical physics solvers handle real-time spatial queries and contact impulses:

  • Broad-Phase vs. Narrow-Phase Collision: Testing collision between every pair of $N$ objects requires $O(N^2)$ calculations. Engines use spatial partitioning data structures—such as Dynamic Bounding Volume Hierarchies (AABB Trees) or Spatial Hashing—during the Broad Phase to prune distant pairs in $O(N log N)$ time. The compute-intensive Narrow Phase (e.g., Separating Axis Theorem SAT in 2D, or Gilbert-Johnson-Keerthi GJK and Expanding Polytope Algorithm EPA in 3D) runs exclusively on overlapping bounding boxes.
  • Sequential Impulse Solvers: Rather than solving massive global matrix equations simultaneously (LCP solvers), Box2D uses iterative Projected Gauss-Seidel (PGS) impulse solvers. Contacts and joints iteratively exchange velocity impulses over multiple iterations (typically 8 velocity iterations, 3 position iterations), converging on a visually stable, non-penetrating equilibrium.
Physics Simulation Pipeline: Broad-Phase to Constraint Solver 1. Integration • Symplectic Euler • Apply Gravity • Velocity Updates 2. Broad Phase • Dynamic AABB Tree • O(N log N) Pruning • Candidate Overlaps 3. Narrow Phase • SAT (2D) / GJK (3D) • Contact Manifolds • Penetration Depth 4. Solvers • Impulse Iteration • Friction Tangents • Position Correction

3. Multiplayer Networking: Reliable UDP, ENet & Client Prediction

Real-time multiplayer games cannot use standard TCP. In TCP, an unacknowledged lost packet triggers Head-of-Line (HoL) blocking: the operating system halts delivery of all subsequent packets until the dropped packet is retransmitted. In a fast-paced game like Teeworlds, stalling input packets for 150ms ruins gameplay.

Instead, game engines build upon UDP (User Datagram Protocol) using custom reliability layers like ENet:

  • Multi-Channel UDP Architecture: Critical messages (e.g., chat messages, player joins) are transmitted on a reliable sequenced channel, while high-frequency state updates (e.g., player position snapshots at 30Hz) are broadcast on an unreliable, unsequenced channel where stale dropped packets are simply ignored.
  • Client-Side Prediction & Server Reconciliation: To eliminate perceived input lag, the local client applies player input immediately to its local simulation. When the authoritative server broadcast arrives 100ms later with the verified position, the client compares the server position against its history buffer, snapping or smoothly interpolating to reconcile errors.
  • Delta Compression: Servers broadcast only the delta changes between the current frame and the client's last acknowledged baseline snapshot, reducing network bandwidth by up to 85%.

4. Recommended Open-Source C++ Codebases for Study

  1. Godot Engine: Exemplary modern C++ architecture. Clean memory allocators, core object reflection, custom container classes avoiding STL bloat, and modular C++ extension bindings.
  2. Battle for Wesnoth: Turn-based strategy game with clean separation between the C++ core engine and Lua scripting for campaign events and AI behaviors.
  3. 0 A.D. (Wildfire Games): Complex real-time strategy (RTS) engine featuring an advanced Entity Component System (ECS), pathfinding via hierarchical pathfinders, and Mozilla SpiderMonkey JS integration.
  4. Teeworlds: Minimalist, hyper-efficient 2D multiplayer shooter. Demonstrates pure C++ UDP networking, delta compression, and rigid physics without external dependencies.