Umbra Engine


Umbra Engine is a custom C++ game engine designed for 2D games, featuring a lightweight Entity-Component-System (ECS) architecture, a multithreaded job system, modular service layer, and full support for real-time game mechanics.

Features

Core Architecture

  • Custom ECS framework inspired by ENTT — bitset-based component matching, typed views, and multi-phase system execution (FrameStartSimulationPreRenderFrameEnd)
  • Scene graph with parent-child transform hierarchy — local/world matrix propagation via DFS each frame
  • Scene management with async transitions and LDtk level editor integration

Multithreading & Parallelism

  • M:N job system — fixed thread pool with work-stealing queue
  • ParallelFor for data-parallel workloads (e.g. texture loading batches)
  • Dependency chains via SubmitAfterJobHandle / JobCompletion primitives with completion callbacks
  • Primitives: Mutex, SpinLock, ConditionVariable, Thread (RAII wrapper)

Rendering

  • Decoupled RenderService — ECS submits RenderQuad draw commands each frame; service handles sort, cull, batch, and flush
  • GLSL shader support via IShader / SfmlShader + MaterialComponent for per-entity shaders
  • DebugDrawer for lines, circles, boxes, and oriented boxes without ECS coupling
  • Sprite-sheet animation system — AnimationClip::FromGrid() helper, frame-rate controlled UV writes

Asset System

  • AssetManager — demand-loaded, path-keyed cache for textures, fonts, and shaders
  • Async variants (GetTextureAsync, GetFontAsync, GetShaderAsync) — callbacks fire on job completion
  • ShaderResource supporting fragment-only and vertex+fragment pipelines

Physics & Collision

  • Dynamic AABB tree for broadphase and Sequential Impulse based collision solver for narrow phase and collision event callbacks
  • PhysicsService + `ECS bridge’ — ECS ↔ PhysicsService sync (creates/destroys bodies, syncs transforms)

Audio

  • AudioService backed by miniaudio — fire-and-forget and looping playback
  • AudioResource integrated into the async asset cache

Diagnostics & Utilities

  • MemoryTracker — hooks global new/delete; per-category atomic stats with live ImGui panel
  • PathUtils — header-only path manipulation (normalize, join, stem, extension, relative/absolute)
  • LDtkEntityComponent — arbitrary field map from LDtk entity layer for designer-driven data

Read up on implementation in my devblog series

Watch the Physics System Demo: