A handcrafted C++ game engine.

Minimal, fully open source, and built for AI to create games with quickly. Multiplayer included.

Version 0.1, in early development by one person.

A spiral galaxy of thousands of sprites, drawn by the Graphics Stress sample.
Graphics Stress, one of the demos below.

Handcrafted

Renderers written directly against DirectX 12, Metal 4 and WebGPU. Its own scene, UI, collision, networking and tools, shaped by one developer.

Minimal, no dependencies

About 26,000 lines of engine code. The build fetches nothing and there are no packages to install. A few small libraries, such as miniaudio and cJSON, sit in the source tree.

Built for AI

Made so AI agents can create games quickly. The rules, traps and recipes are written down for them, every game has the same shape, and headless builds let a game run without a window.

Fully open source

The engine and every sample on this page are on GitHub under the MIT licence.

Play

These run right here in your browser, with WebGPU.

  1. 01Tower ClimbLeap between two walls and climb as high as you can.Touch or keyboard
  2. 02SurvivorsHold out against growing waves, then spawn thousands more.Keyboard required
  3. 03EvolutionCreatures roam and reproduce across a procedural landscape.Keyboard required
  4. 04Graphics StressA turning spiral galaxy, with dials for every render path.Touch or mouse
  5. 05UI DemoA small tour of the engine’s UI widgets.Keyboard for most controls

Write a game

A game is a class with callbacks, in its own repository. This one moves a sprite with the arrow keys.

Getting started

// game_main.cpp
#include "game/game_main_class.h"
#include "moksha/client/game/game_factory.h"

MOKSHA_GAME(MyGame::GameMain, "My Game")

// game/game_main_class.cpp
void MyGame::GameMain::Update(double deltaTime) {
    ME::Game::Update(deltaTime);
    const float speed = 80.0f * static_cast<float>(deltaTime);
    ME::Vec3 pos = mainScene->GetPlayer().GetPosition();
    if (engine->input->GetKeyDown(ME::Input::KeyCode::LeftArrow)) pos.x -= speed;
    if (engine->input->GetKeyDown(ME::Input::KeyCode::RightArrow)) pos.x += speed;
    if (engine->input->GetKeyDown(ME::Input::KeyCode::UpArrow)) pos.y += speed;
    if (engine->input->GetKeyDown(ME::Input::KeyCode::DownArrow)) pos.y -= speed;
    mainScene->GetPlayer().SetPosition(pos);
}

What’s in it

Rendering
Native DirectX 12, Metal 4 and WebGPU backends draw sprites and UI, with up to 100,000 instanced sprites. A headless backend runs the same game code with no window.
Scene
Plain struct-of-arrays data with fixed capacities, read by the renderer each frame. Deliberately not an ECS.
App loop
The engine owns the entry point and the frame. Your game supplies callbacks, on a fixed step with variable-rate update and rendering.
Collision
AABB overlap detection with layers and callbacks. It reports hits and leaves movement to you.
Animation and audio
Data-driven sprite clips and atlases in JSON. Music and sound effects through miniaudio.
Input and UI
Keyboard and mouse, with touch on iOS and web. A small retained-mode UI with panels, labels, images and buttons.
Multiplayer
A game server module, UDP and TCP sockets, a binary game protocol and a content server. On native platforms for now, not yet on web.
Tooling
An asset cook, a content server, a test framework, and core libraries for math, fixed-point numbers, random numbers and files.

Platforms

TargetGraphicsStatus
WindowsDirectX 12Supported
macOSMetal 4Supported on Apple silicon, macOS 26+
iOSMetal 4Supported on iPhone, iOS 26+
WebWebGPUSupported, without networking
LinuxNone yetServers and headless clients only
AndroidVulkanPlanned

Principles

  • No exceptions and no RTTI. Failures come back as return values.
  • Caller-owned, fixed-capacity memory over growing containers.
  • No singletons. Systems receive explicit context.
  • A general engine first. No API is shaped around a single game.
  • Games depend on the engine, and never the other way round.