AssemblyEngine is a Windows game engine built entirely in managed C# with Silk.NET for cross-platform windowing, input, and Vulkan rendering. The current implementation targets Windows x64 and Windows ARM64, uses HTML/CSS files for HUD and overlay rendering, and can present the managed framebuffer through Vulkan when that backend is explicitly requested.
- Fully managed C# engine with no native compilation dependencies — just .NET 10 SDK.
- Cross-platform windowing and input through Silk.NET, with Vulkan rendering support.
- Keep gameplay code approachable in C# with a clean, readable engine architecture.
- Use simple HTML/CSS for in-game overlays instead of a separate browser process or a custom widget toolkit.
- Grow from a Windows prototype into a multi-platform engine over time.
- Supported platforms: Windows x64, Windows ARM64
- Engine: fully managed C# with Silk.NET windowing and input
- Runtime: .NET 10
- Rendering: unified managed 2D/3D color + depth surface, opt-in Vulkan swapchain presentation, software GDI fallback
- Multiplayer: managed direct peer-to-peer and localhost sessions over the runtime multiplayer service
- Sample games: Dash Harvest in
sample/basic, Citadel Breach insample/fps, Frontier Foundry insample/rts, Lantern Letters insample/visual-novel - UI system: runtime HTML/CSS parsing with a built-in text renderer
flowchart LR
Game[Game project] --> Runtime[Managed runtime]
Runtime --> SilkNET[Silk.NET windowing and input]
Runtime --> UI[UI system]
Runtime --> Vulkan[Vulkan presenter]
Runtime --> Software[Software GDI fallback]
The game project uses the managed runtime, which uses Silk.NET for cross-platform windowing and input. The runtime's unified renderer feeds either a Vulkan presenter or the software GDI fallback.
- Resizable 2D and lightweight 3D applications on Windows x64 and Windows ARM64 with windowed, maximized, and borderless fullscreen presentation modes
- Unified 2D and 3D rendering on the same managed color/depth surface
- Immediate-mode style drawing via pixel, line, rectangle, circle, mesh, and cube primitives
- BMP sprite loading and drawing through the same managed renderer used by 3D geometry
- WAV audio playback
- Scene-based games with entities, components, and scripts
- HTML/CSS HUD overlays updated from C# scripts
- Direct host or join multiplayer flows from managed scripts through
GameEngine.Multiplayer - Vulkan swapchain presentation when
GameEngine.PresentationBackendis set toGraphicsBackend.Vulkan, with software GDI fallback
If Vulkan is explicitly requested but the runtime cannot load the required swapchain entry points from the active driver stack, AssemblyEngine logs a warning and continues on the software GDI path instead of failing startup.
- Bootstrap the local toolchain:
.\setup.ps1The setup script validates and installs any missing prerequisites:
- .NET 10 SDK
If you only want an audit, run:
.\setup.ps1 -CheckOnly- Audit the local toolchain without changes:
.\setup.ps1 -CheckOnly- Build the runtime and sample game:
powershell -NoProfile -ExecutionPolicy Bypass -File .\shell\build.ps1To publish the visual novel sample instead of Dash Harvest, pass the sample selector:
powershell -NoProfile -ExecutionPolicy Bypass -File .\shell\build.ps1 -Sample visual-novelTo publish the 3D FPS sample instead, run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\shell\build.ps1 -Sample fpsTo publish the RTS sample instead, run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\shell\build.ps1 -Sample rtsTo publish self-contained bundles for every sample into isolated folders, run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\shell\publish_samples.ps1 -TargetArchitecture x64For Windows ARM64 sample bundles, run:
powershell -NoProfile -ExecutionPolicy Bypass -File .\shell\publish_samples.ps1 -TargetArchitecture arm64That command writes per-sample runnable outputs to build/sample-publish/<architecture> and marks them as sample binaries rather than source or engine SDK artifacts.
- Run the sample:
.\build\output\SampleGame.exeOr, after using -Sample visual-novel:
.\build\output\VisualNovelSample.exeOr, after using -Sample fps:
.\build\output\FpsSample.exeOr, after using -Sample rts:
.\build\output\RtsSample.exeDash Harvest controls:
WASDor arrow keys moveSpacedashesRorEnterrestarts after game overF1opens the display settings panel
Dash Harvest now also plays generated 8-bit SFX for dashes, pickups, hits, wave transitions, and game over.
Dash Harvest also includes a small 3D cube backdrop rendered through the same surface as its 2D gameplay and HUD, which makes it a useful sanity check for the unified renderer and Vulkan presenter.
To request Vulkan in the basic sample, set presentationBackend to vulkan in sample/basic/sample-settings.json.
Lantern Letters controls:
Space,Enter, orRight Arrowadvance dialogueTabtoggles skip mode- Hold
ShiftorControlto fast reveal the current line F5saves andF9loads the current dialogue stateHomerestarts the scene
Lantern Letters also plays generated 8-bit UI and dialogue SFX for advancing text, skip toggles, save/load, restart, and chapter end.
Citadel Breach controls:
WASDmove- Mouse or
LeftandRightarrows look - Left mouse or
Spacefires - Hold
Shiftto sprint F1toggles the control panelRorEnterrestarts after mission clear or failure
Frontier Foundry controls:
- The sample now opens on a main menu with single-player, direct peer host/join, and localhost host/join options
- Click the callsign, IPv4, or port fields to edit them, then use the lobby to mark ready and start the mission
- Left drag selects units; hold Shift to add or Ctrl to remove
- Right click issues move or harvest orders
- Right click with no selection moves the HQ rally point
- Left click the minimap instantly recenters the camera
- Middle click snaps the camera to the cursor position
Qqueues a worker andEqueues a guard1,2, and3select workers, guards, or all units, andSpacefocuses the current selection or HQ- Arrow keys or moving the cursor to the screen edge pans the camera
F1toggles the command brief andRorEnterrestarts after victory or defeat
The sample persists display and lobby preferences in sample-settings.json. Window mode, Resolution, VSync, UI scale, playerName, peerAddress, and multiplayerPort all survive restarts, and maximize or restore events now resize the engine surface dynamically.
If you want to inspect or drive a running game from an AI agent, the repo also includes a stdio MCP server in src/tools/AssemblyEngine.RuntimeMcpServer. It can launch a game, tail structured runtime logs, return live runtime state, capture the current game framebuffer, and inject keyboard or mouse input. The checked-in .vscode/mcp.json file includes an assemblyengine-runtime server entry so current VS Code builds can auto-discover it from the workspace. See Runtime MCP server.
Typical runtime MCP workflow:
- Start the
assemblyengine-runtimeMCP server from the workspace or your MCP client. - Call
launch_gamewithbuild/output/SampleGame.exeor another AssemblyEngine game executable. - Use
get_session_statusandwait_for_logsto inspect runtime state and tail logs. - Use
capture_screenshotto grab the current rendered frame andsend_keyor mouse tools to drive the game.
If you prefer to iterate from an IDE, build sample/basic/SampleGame.csproj, sample/fps/FpsSample.csproj, sample/rts/RtsSample.csproj, or sample/visual-novel/VisualNovelSample.csproj directly with dotnet build.
The engine is designed so that a game project mainly needs a scene, a script, and an entry point.
using AssemblyEngine.Core;
using AssemblyEngine.Engine;
using AssemblyEngine.Scripting;
namespace HelloAssemblyEngine;
public sealed class MainScene : Scene
{
public MainScene() : base("Main") { }
public override void OnLoad()
{
var player = CreateEntity("Player");
player.Position = new Vector2(128, 128);
var collider = player.AddComponent<BoxCollider>();
collider.Width = 32;
collider.Height = 32;
}
}
public sealed class PlayerScript : GameScript
{
public override void OnDraw()
{
var player = Scene.FindByName("Player");
if (player is null)
return;
Graphics.DrawFilledRect(
(int)player.Position.X,
(int)player.Position.Y,
32,
32,
new Color(110, 240, 255));
}
}
public static class Program
{
public static void Main()
{
var engine = new GameEngine(800, 600, "Hello AssemblyEngine");
engine.Scenes.Register("main", new MainScene());
engine.Scripts.RegisterScript(new PlayerScript());
engine.Scenes.LoadScene("main");
engine.Run();
}
}GameEngine owns the frame loop, Scene creates and manages entities, and GameScript handles per-frame behavior. Entities now expose both 2D helpers and 3D transform fields (Position3D, Scale3D, Rotation3D) so gameplay code can stay in one scene graph while using either draw style. The sample project in sample/basic shows a larger version of the same pattern with a HUD overlay, arcade loop, and a simple rotating 3D backdrop.
| Path | Purpose |
|---|---|
src/runtime |
Managed engine runtime, scene system, rendering, and UI stack |
sample/basic |
Playable 2D arcade sample built on top of the runtime |
sample/fps |
Playable 3D FPS arena sample built on top of the runtime |
sample/rts |
Playable top-down RTS sample with harvesting, production, and enemy raids |
sample/visual-novel |
Visual novel sample with dialogue, save/load, sprites, and parallax |
shell |
Build and setup scripts |
docs |
Project documentation and diagrams |
build/output |
Generated binaries and copied UI assets |
Near-term priorities:
- Stabilize the managed runtime and Silk.NET platform layer
- Improve the asset and tooling story around sprites, audio, and UI
- Keep the architecture readable and easy to extend
- Expand Vulkan rendering capabilities
Longer-term platform targets:
- Linux
- macOS
- iOS
- Android
- WebAssembly
Contributions are welcome, especially around rendering features, sample content, documentation, and additional platform work. Start with CONTRIBUTING.md and the implementation guide so changes follow the existing layer boundaries.
AssemblyEngine is licensed under the Apache License 2.0. See LICENSE and NOTICE for the license text and attribution.