Project 15: Mini Game Engine

A complete 2D/3D game engine combining all previous concepts: renderer, ECS, audio, physics, hot-reload, profiling, and asset pipeline.

Quick Reference

Attribute Value
Primary Language Odin
Alternative Languages C++, Rust
Difficulty Level 5: Master
Time Estimate 2-3 months
Knowledge Area All of the Above
Tooling All previous projects combined
Prerequisites All previous projects (or equivalent experience)

What You Will Build

A complete 2D/3D game engine combining all previous concepts: renderer, ECS, audio, physics, hot-reload, profiling, and asset pipeline.

Why It Matters

This project builds core skills that appear repeatedly in real-world systems and tooling.

Core Challenges

  • Integrating all subsystems → maps to system architecture
  • Clean API design → maps to Odin idioms and patterns
  • Performance optimization → maps to profiling and tuning
  • Making it usable → maps to ergonomics and polish

Key Concepts

  • Engine Architecture: “Game Engine Architecture”
  • All Previous Concepts: Memory, graphics, audio, ECS, etc.
  • API Design: Making it pleasant to use
  • Documentation: Odin’s built-in doc system

Real-World Outcome

$ odin run my_engine_editor

Odin Game Engine v0.1
---------------------

[Editor window opens with scene view, inspector, and console]

Engine Features:
  ✓ Vulkan/OpenGL/Metal renderer
  ✓ Entity Component System (SOA-based)
  ✓ Physics (2D + 3D)
  ✓ Audio engine with effects
  ✓ Hot-reload for game code
  ✓ Asset pipeline (models, textures, audio)
  ✓ WASM export for web
  ✓ Built-in profiler
  ✓ Scripting via Odin DLLs

Create a new game:
  1. Write game code using engine API
  2. Hot-reload changes instantly
  3. Build for native or web

Example game.odin:
-----------------
package game

import engine "my_engine"

@(export)
game_init :: proc(ctx: ^engine.Context) {
    player := engine.create_entity(ctx)
    engine.add_component(ctx, player, engine.Transform{{0, 0, 0}, {0, 0, 0}, {1, 1, 1}})
    engine.add_component(ctx, player, engine.Sprite{"player.png"})
    engine.add_component(ctx, player, engine.Rigidbody{mass = 1.0})
}

@(export)
game_update :: proc(ctx: ^engine.Context, dt: f32) {
    input := engine.get_input(ctx)

    for entity in engine.query(ctx, {Transform, Player}) {
        if input.key_down[.SPACE] {
            engine.apply_force(ctx, entity, {0, 500, 0})
        }
    }
}

Implementation Guide

  1. Reproduce the simplest happy-path scenario.
  2. Build the smallest working version of the core feature.
  3. Add input validation and error handling.
  4. Add instrumentation/logging to confirm behavior.
  5. Refactor into clean modules with tests.

Milestones

  • Milestone 1: Minimal working program that runs end-to-end.
  • Milestone 2: Correct outputs for typical inputs.
  • Milestone 3: Robust handling of edge cases.
  • Milestone 4: Clean structure and documented usage.

Validation Checklist

  • Output matches the real-world outcome example
  • Handles invalid inputs safely
  • Provides clear errors and exit codes
  • Repeatable results across runs

References

  • Main guide: LEARN_ODIN_PROGRAMMING_LANGUAGE.md
  • “Game Engine Architecture” by Jason Gregory