KernelAPI reference
Namespace MicroEngine.Core
The game and its loop: Game, settings, runners and sessions, launchers and platform composition, scripted input, saves, content files, achievements, application identity, the headless platform.
Guide: Game lifecycle and time
Classes
The saved state of one achievement.
What is written to the save slot. Entries are keyed by achievement id.
Owns a game’s achievements: the catalog, progress, unlocking and persistence. Games decide when something happened and report it with Unlock, AddProgress or SetProgress; the tracker guarantees that an achievement unlocks (and raises Unlocked) exactly once, across sessions.
One entry of a game’s achievement catalog. Id is the stable key stored in saves, so names and descriptions can change freely. Goal of 1 is an immediate achievement; larger goals are progressive (“win 10 battles”).
The application identity a game declares once, in its project file (docs/guide/app-identity.md):
ApplicationTitle, ApplicationId, Version, MicroEngineIcon and
MicroEngineOrientation. The MicroEngine build targets write it into the game assembly; packaging turns it into
each system’s metadata, and platforms read it at run time (application name, window icon, phone orientation).
Assets started by Preload: progress for a loading screen, errors, and a way to wait.
Loads, shares and releases a game’s content files (Game.Assets): images as textures, packing tools’ atlases,
folders of images packed into one atlas, and TTF/OTF fonts. The same request returns the same object, so a texture
used by ten scenes is decoded and uploaded once, whichever scopes ask for it; an asset is disposed when the last scope
holding it releases it.
A content file that could not be loaded: missing, unreadable, in an unsupported format, or named with the wrong letter case.
Several input sources read as one: a key or button is down when any source has it down; the stick or axis with the largest deflection wins.
Locates a game’s asset files. By default the root is the Content folder next to the
executable (games copy it there at build time). Missing files fail with the full path so a
broken install or a typo is obvious. A content source (IContentSource) over a
FolderContentSource.
A text file that describes a run that stopped on an error, for a tester to send: the game and engine versions, the operating system and runtime, the platform’s facts (IPlatformDiagnostics), the last measured frame and its slowest systems when Diagnostics measured, and the error with its stack trace. The desktop launcher writes one when a game’s run fails and names it on standard error.
The colours Physics uses.
Shapes and text any code can ask for while the game runs, drawn above the scenes at the end of the frame (DebugDraw): a ray an enemy casts, the box a move swept, a path, a value next to an entity. Calls do nothing while Enabled is off, so they can stay in shipped code.
A display (monitor) as the system reports it.
One JSON file per slot in a directory (desktop and tests).
Measures a run frame by frame and the phases of its start, for –profile and benchmarks. It only measures
what the engine itself sees: when EndFrame returns, not when the display shows the frame
(presentation times need the platform’s own tools). Samples go into a buffer allocated up front, so profiling
adds no allocations to the frames it measures; a run without a profiler does not measure anything.
What a profiled run looked like. MotionError is the measure of uneven motion: for every frame, how far the game time it advanced differs from the wall time that passed, so a frame that repeats the previous picture or jumps two steps counts even when every frame took the same time.
The game’s live measurements (Diagnostics): the last frame’s times, allocations, collections, graphics work and audio voices, and the time of every system of the frame schedule. Off by default; a run measures while Enabled is set or while a tool listens to the engine’s meter (MeterName), and costs nothing measurable otherwise.
The one launch path of every host: desktop (GameLauncher), browser pages, Android and iOS apps and
tests compose the same way and decide a run the same way. A host states its defaults (its platforms, where content
files are), the game’s Configure entry point composes the rest (HostBuilder), and the
LaunchRequest decides the run: a script means deterministic time and seed 1 on every host; a run in
deterministic time asks the platform not to wait for the display and for no sound device unless the launch asks for
one; a real-time run whose game shows a start screen starts gamepads after the first frame.
The command line every desktop game accepts, on any backend: a thin caller of the launcher model every host shares (GameHost, LaunchRequest). Supported arguments:
--script FILEplay scripted input (see [InputScript](/docs/api/microengine.core.inputscript/)); implies deterministic time unless--timesays otherwise.--captures DIRdirectory for script captures (default ./captures).--platform NAMErun on that platform of the catalog (default:MICROENGINE_PLATFORM, else the first one that can run here);--list-platformsprints them and exits.--headlessrun without a window (no captures are written); the same as--platform headless. A headless run is in deterministic time unless--timesays otherwise (the headless platform's [RunPreset](/docs/api/microengine.core.runpreset/)).--hiddenrender in a hidden window (captures still work); it implies nothing about time or sound.--time realtime|deterministichow the loop advances time ([TimeMode](/docs/api/microengine.kernel.timemode/)): with the wall clock, or one fixed step per frame; by default the game's choice, else the platform's [RunPreset](/docs/api/microengine.core.runpreset/) (headless: deterministic), else real time; a script means deterministic.--frames Nstop after N updates;--seed N;--scale N;--mute.--reportprint the platform that runs and whether it has audio before the game starts (package checks).--audio auto|device|silentwhere sound may go ([AudioOutput](/docs/api/microengine.core.audiooutput/));auto(the default) asks for no physical device when the run is in deterministic time (scripts,--time deterministic), so checks are never heard, and for one otherwise (the headless platform has none).--audio-capture FILEplay nothing aloud and write what would have been heard as a WAV ([CaptureAudioDevice](/docs/api/microengine.audio.captureaudiodevice/)).--gpu auto|high-performance|power-savingthe GPU to ask for on a machine with two ([GpuPreference](/docs/api/microengine.core.gpupreference/)).--renderer NAME[,NAME...]graphics APIs to try first ([Renderers](/docs/api/microengine.core.graphicssettings/#MicroEngine_Core_GraphicsSettings_Renderers)).--graphics NAMEthe graphics device to draw with, on platforms that offer several: SDL'ssdl-rendererorsdl-gpu([Device](/docs/api/microengine.core.graphicssettings/#MicroEngine_Core_GraphicsSettings_Device)).--vsync on|offwait for the display's refresh or not ([VSync](/docs/api/microengine.core.graphicssettings/#MicroEngine_Core_GraphicsSettings_VSync)).--fps-limit Ndraw at most N frames per second; 0 removes the game's limit ([FrameRateLimit](/docs/api/microengine.core.graphicssettings/#MicroEngine_Core_GraphicsSettings_FrameRateLimit)).--window windowed|fullscreen|exclusivethe window mode ([WindowMode](/docs/api/microengine.core.graphicssettings/#MicroEngine_Core_GraphicsSettings_WindowMode)).--display Nopen on display N, counted from 0 ([Display](/docs/api/microengine.core.graphicssettings/#MicroEngine_Core_GraphicsSettings_Display)).--pacing display|measuredcount frame time in refresh periods of the display (the default) or as measured ([PaceToDisplay](/docs/api/microengine.core.runoptions/#MicroEngine_Core_RunOptions_PaceToDisplay)).--profile FILEmeasure every frame and the start phases ([FrameProfiler](/docs/api/microengine.core.frameprofiler/)), print a summary and write the results as JSON, or CSV when FILE ends in .csv.--state-trace FILEhash the simulation state after every fixed step ([StateTrace](/docs/api/microengine.core.runoptions/#MicroEngine_Core_RunOptions_StateTrace)) and write one line per step with each section's hash ([StateTrace](/docs/api/microengine.kernel.statetrace/)'s text format): two runs of the same build, script and seed write the same file, and [FirstDivergence](/docs/api/microengine.kernel.statetrace/#MicroEngine_Kernel_StateTrace_FirstDivergence_MicroEngine_Kernel_StateTrace_MicroEngine_Kernel_StateTrace_) names where two traces part.
A run in deterministic time also asks the platform, through explicit request options, not to wait for the display
(WaitForDisplay) and for no sound device (–audio auto); a run in real time
whose game shows a start screen asks it to start gamepads after the first frame
(StartGamepadsAfterFirstFrame). The platform itself never knows the time mode.
Browser pages, phone apps and tests apply the same rules through GameHost.
Returns a process exit code: 0 on success, 1 on a game or platform error, 2 on bad arguments.
The loop, one frame per Tick. It owns time: the platform only supplies a monotonic clock
(Clock), and the engine’s FrameClock turns each frame’s time into fixed
steps following the game’s TimeSettings (at most MaxStepsPerFrame a frame, frames of at
most MaxFrameDelta). Each frame runs the engine’s frame schedule: the per-frame phases, the four fixed phases
once per step, then the update, drawing and presentation phases. In deterministic time every frame is exactly one
step, which makes scripted runs reproducible. Each frame starts with the platform’s event pump
(PumpEvents), whose events become the engine’s lifecycle events
(IEngineLifecycle) before the frame’s steps. Hosts that cannot block, such as a browser driving
frames from requestAnimationFrame, call Tick themselves; errors are captured, never thrown.
Runs a game to completion on platforms that own their thread (desktop, headless): GameLoop ticked in a blocking loop.
The game’s screen while it runs (Screen): the displays, which one the game is on, and the options that can change without restarting. Changes apply where the platform allows; read a property back to see what applies (a browser or phone keeps its own window, a headless run has none).
Runs one game at a time for hosts that drive frames themselves and outlive a run, such as a browser page: each Start builds a fresh game and platform, Tick runs one frame, and the end of a run (quit, error, Stop) shuts the game down and releases the platform, so the host can show its own screen and start again without reloading.
Window/backbuffer settings a game declares. The virtual size is the canvas everything is drawn on: 320×180 pixel art by default, or a high-resolution canvas such as 1280×720 or 1920×1080 with HighResolution2D.
The game’s two views and the mapping between them (Views): the world view (the canvas, at the canvas’s resolution, placed in the window by the presentation) and the UI view (the window’s resolution, in UI units), drawn over it. Positions convert between window pixels, canvas pixels and UI units, and the pointer is given in each view; the UI view gets it first (PointerOnUi).
Base class for a game. Subclasses declare Settings, build content in Load and push the first scene. The runner owns the loop.
The graphics options a game starts with (Graphics). Every option has a sensible automatic
default; the launcher’s options (–platform, –renderer, –vsync, –fps-limit, –gpu,
–window, –display) override them for one run, and Screen changes the ones a platform
can change while the game runs. A game that offers a graphics menu saves Current and returns
it from Settings at its next start. VSync, the frame limit and UpdateRate
are independent: VSync waits for the display, the limit caps frames per second, the update rate is the simulation’s.
A graphics device for tests: textures keep their size and filter but hold no pixels (unless KeepsPixels); creations, uploads and live textures are counted.
An input backend tests drive by hand: device events sent with Send are delivered at the next drain, in order; key labels can be set as a keyboard layout would print them; rumbles and text-input switches are recorded.
Keys, a gamepad and a pointer that tests set by hand.
A windowless platform: no devices, and a renderer that counts calls (or, with Rasterize, also records them and draws them with the CPU reference rasterizer). Used by automated tests and CI to play whole games through scripts. Its surface has the canvas’s size; tests drive its events by hand (Resize, Focus, Suspend, Resume, RequestQuit), which the next event pump delivers in order. Its run preset (Preset) is deterministic time: a stated default of this testing composition that a run or a game overrides. Nothing the platform does depends on the time mode.
Counts draw calls and tracks camera balance so tests can assert rendering ran correctly. Created with a graphics device, it also rasterizes: it records each draw as a line of text (Commands) and draws it on Frame with the CPU reference rasterizer, which follows the engine’s rendering rules exactly.
A touch screen for tests: fingers go down, move and lift by hand, the size, safe area and density can change (a rotation, a notch), vibrations are counted, and DrawOverlay records what the overlay draws.
The game’s side of a HostBuilder: choosing the game, the platforms a host offers and changes to the
platform request. A game’s Configure entry point calls these; every host (desktop, browser, phones, tests)
reads them through GameHost.
A deterministic input script, keyed by update number. Text format, one command per line:
# comment30 press confirm # down for 2 updates60 hold right 90 # down for 90 updates60 down jump / 75 up jump # explicit edges200 capture title.png240 touch 1 dpad 1 0 # finger 1 down on the d-pad, one radius to the right (or moves there)250 tap 2 jump # finger 2 taps the "jump" control (lifted 2 updates later)260 touch 3 0.5,0.5 # finger 3 at the middle of the screen (fractions of its size)300 lift 1320 prompts gamepad playstation # name controls as on a PlayStation pad (keyboard, gamepad, touch or auto)400 key Space down # the script's keyboard: a key by position (a Key name) goes down, or up410 keytap Z # down and up within one frame420 pad 2 add playstation # the script's gamepad 2 connects (xbox, playstation or nintendo)430 pad 2 A down # a button of pad 2 (a PadButton name) goes down, or up440 pad 2 LeftX -0.8 # an axis of pad 2 (a PadAxis name) moves450 pad 2 remove460 mouse 160,90 down # the script's mouse moves to a point in canvas pixels (and its button goes down or up)470 wheel 1 # the wheel turns one notch away from the player480 text Ana # text typed (the rest of the line), read while text input is on900 quit“@+N” instead of an absolute number means N updates after the previous command. Touch commands go through the game’s VirtualControls with the same hit testing as real fingers. The device commands send events from the script’s own devices (ScriptKeyboard, ScriptMouse, ScriptPad) through the engine’s input layers, exactly as a backend’s would; each device is announced before its first event.
The launcher command line with the engine’s own types (see GameLauncher): a typed view of a LaunchRequest, with the seed and the time mode resolved by its rules.
Measures wall-clock time for desktop platforms.
The platforms a host can choose from, in order of preference: the first one that can run here is the default.
Hosts select by name (a –platform argument, a setting), never game code.
PlatformConfigurationException
A platform request that cannot be met: unknown or unsupported profile, or a part the profile does not let a host replace.
A named way to build an IPlatform: an official backend (“sdl”, “raylib”, “headless”) or one a developer registers. The profile decides which parts a host may replace (Replaceable), because some subsystems share state with the window and cannot be swapped independently.
What a host asks of a platform: the game’s settings, window options and any subsystem it supplies itself. Every option is explicit and has a documented default; none depends on how the loop advances time (that is the loop’s business only, TimeMode). A backend honours the supplied parts by building its audio device with CreateAudio and its input with CombineInput; Create checks that it did.
An IOverlayCanvas that keeps a list of the shapes drawn, for tests.
Options shared by every launcher: scripted input, captures and run limits.
Defaults a composition states for the runs it hosts when neither the run (RunOptions) nor the game (Configure) chooses: a stated preset value, never a platform behaviour. A platform offers it as a capability (TryGetCapability``1); the headless platform’s preset is Deterministic, so tests that run a game headless are reproducible with no option. The platform behaves the same whatever the mode the run ends up with.
How a run ended.
Small JSON persistence for settings and progress. Without a directory or a storage of its own, a store keeps its slots
in the platform’s default medium (DefaultStorage): files under the user’s data folder
(DefaultDirectory), and the page’s localStorage in browsers. A composition can hand a game another medium
(HostBuilder.Storage); tests pass a temporary directory.
Corrupt or missing data yields null instead of crashing the game; corrupt data is set aside
(“<slot>.corrupt.json” for files) so the next save cannot destroy it. A slot that exists but could not be
read (locked file, blocked browser storage) is never written by this store, because the game is then
running with fresh progress that would replace the real one. Failed writes return false instead of
throwing, so a full disk or browser storage quota leaves the game running with its progress in memory.
Builds the image the player sees from the two views, as the platforms compose a frame.
The screen a game opens on while it loads: its start-screen image (MicroEngineSplashImage, by default the
icon) centred on its colour (MicroEngineSplashColor), and “Made with MicroEngine” below when the game asks
for it (MicroEngineSplashBranding). Phones and browsers show the same image and colour before the engine
starts (launch screens, the loading page), so the player sees one continuous screen from the tap to the first frame.
GameLoop draws it once, before Load, on platforms that run in real time; it adds no
delay, and an error while loading is reported as before.
The window sizes desktop platforms open and allow, shared by every backend so they agree.
Structs
A snapshot of one achievement: its definition, accumulated progress and whether it is unlocked.
One loaded asset, as Loaded lists it.
Totals over a scope and its children (Statistics).
One frame as FrameProfiler measured it. Times are in milliseconds.
What a frame cost, as LastFrame reports it. Times are in milliseconds of real time.
Percentiles of one frame measurement, in milliseconds.
One recorded drawing call.
How long one system of the frame schedule took during the last frame (Systems).
Interfaces
What a platform can change about its window and presentation while the game runs (Screen uses it). A capability (TryGetCapability``1): platforms without a window (headless) or whose host owns these choices (browsers, phones) do not offer it, or report that a change did not apply.
Facts a platform can report about itself for logs and profiles: the graphics API in use, VSync, the graphics adapter when the backend can name it. Keys are short lower-case words; values are free text. A capability (TryGetCapability``1).
Everything a backend provides: the host (IPlatformHost: clock, events, main surface, capabilities, whether it may block) plus, until the graphics, input and audio contracts are split from it, the renderer that draws into the virtual canvas and the graphics, input and audio devices.
Where a SaveStore keeps its slots: the platform’s storage contract
(IStorage: named texts that are written whole, failures as IOException or
UnauthorizedAccessException) under the name saves have always used.
The UI view of a platform that draws at the window’s resolution: a capability (TryGetCapability``1) of the SDL and raylib platforms and of the headless platform. The world is drawn into the canvas (BeginFrame) and scaled into WorldFrame; the UI view is drawn in UI units (window pixels divided by UiScale) and composited over it, so its text and shapes have the window’s resolution whatever the canvas’s.
The captures of a platform that has a UI view (IScreenView), a capability of the SDL, raylib and headless platforms (TryGetCapability``1). A run’s captures (SaveScreenshot) show what the player sees: a frame that drew a UI is captured as the window, the world scaled into its frame with the UI view composited over it (CaptureScreen); a frame that drew none is captured as the canvas, as before the UI view existed. Tests that need the world alone read CaptureWorld or write SaveWorldScreenshot.
Enums
Screen orientations a game allows on phones (MicroEngineOrientation in its project).
Where a run’s sound may go (AudioOutput, the launcher’s –audio).
Where a DebugDraw item is placed.
Which GPU a game prefers on machines with an integrated and a dedicated one. The system has the last word: on Windows, Direct3D 11 and OpenGL use the adapter Windows assigns to the application (Settings, Display, Graphics), which no backend overrides; SDL passes the preference to its Metal (macOS, iOS) and GPU (Direct3D 12, Vulkan, Metal) renderers; raylib’s OpenGL ignores it.
The subsystems a host may supply to a profile instead of the profile’s own.
How the game’s window covers the screen (WindowMode, WindowMode).