Hello Engine walkthrough
Hello Engine is the smallest complete MicroEngine game: a procedural star sprite you move with the arrow keys, a synthesized sound and a particle burst on confirm, and a looping song. It is one file of about 65 lines, and every concept it uses scales up unchanged to the four full games. This page walks through it top to bottom.
Source: samples/HelloEngine/Program.cs.
Controls
Arrows (or WASD) move the star; Z or Space plays a sound and bursts particles. The sample lives in the engine’s repository
(samples/HelloEngine), is MIT licensed like the engine, and may be copied into your own games; this page shows its
code in full.
1. Entry point
using System.Numerics;using MicroEngine;using MicroEngine.Audio;using MicroEngine.Core;using MicroEngine.Graphics;using MicroEngine.Desktop;using MicroEngine.Scenes;
return DesktopLauncher.Run(new HelloGame(), args);The program is a top-level statement. DesktopLauncher.Run parses the launcher flags (--script, --hidden,
--captures, …), creates a window on the default platform (SDL) sized from the game’s settings, runs the loop and returns a process
exit code: 0 on success, 1 on a game error, 2 on bad arguments.
2. The game class
internal sealed class HelloGame : Game{ public override GameSettings Settings { get; } = new("Hello MicroEngine") { Background = Color.Hex("1d2b53") }; public SpriteAtlas Atlas { get; private set; } = null!; // ... protected override void Unload() => Atlas.Dispose();}Settingsdeclares the window title and, through the record’s defaults, a 320x180 virtual canvas drawn at scale 4 and simulated at 60 updates per second.Backgroundis the clear colour of every frame.Atlasholds the textures built inLoad;Unloadreleases them when the game shuts down.
3. Loading content once
protected override void Load(){ var palette = Art.Palette("o=#000000", "y=#ffec27", "w=#fff1e8"); var star = PixelImage.FromMap(palette, "....o....", "...oyo...", "ooooyoooo", "oyyywyyyo", ".oyyyyyo.", "..oyyyo..", ".oyyoyyo.", "oyyo.oyyo", "ooo...ooo"); Atlas = new SpriteAtlasBuilder().Add("star", star, new Vector2(4.5f, 4.5f)).Build(Graphics); Audio.AddSound("ding", Synth.Render(new SfxParams { Wave = Wave.Square, Frequency = 880, Arpeggio = [1f, 1.5f], Sustain = 0.05f, Decay = 0.2f })); Audio.AddMusic("theme", new Song(120).Track(Instrument.Lead, "C5 - E5 - G5 - E5 - | C5 - - - . . . .").Track(Instrument.Bass, "C3 . C3 . G2 . G2 .").Drums("k . h . s . h .").Render()); Scenes.Push(new HelloScene(this));}Load runs once, after the platform exists. It is the place to build every asset; never build art or sounds per
frame.
| Line | What it does |
|---|---|
Art.Palette(...) |
Maps characters to colours; characters not in the palette, such as ., stay transparent |
PixelImage.FromMap |
Builds a CPU image from text rows, one character per pixel |
SpriteAtlasBuilder().Add("star", star, origin) |
Packs the image into a texture; the origin (4.5, 4.5) is the sprite’s centre, used as its pivot |
.Build(Graphics) |
Uploads the atlas through the platform’s IGraphicsDevice |
Synth.Render(new SfxParams {...}) |
Synthesizes a square-wave chime with a two-step arpeggio into an AudioClip |
new Song(120).Track(...).Drums(...).Render() |
Renders a 120 BPM step-sequenced song with lead, bass and drums |
Scenes.Push(new HelloScene(this)) |
Puts the first scene on the stack |
4. The scene
internal sealed class HelloScene(HelloGame game) : Scene{ private readonly ParticleSystem _particles = new(); private Vector2 _position = new(160, 100);
public override void Enter() => Audio.PlayMusic("theme"); // ...}A Scene is one screen of the game. It reaches the game’s Input, Audio and Font directly. Enter runs when
the scene becomes active; here it starts the music.
Update
public override void Update(float dt){ var move = new Vector2(Input.Axis("left", "right"), Input.Axis("up", "down")); _position += move * 90 * dt; if (Input.Pressed("confirm")) { Audio.Play("ding", pitchJitter: 0.05f); _particles.Emit(_position, new ParticleSpec { StartColor = Color.Hex("ffec27"), EndColor = Color.Hex("ff004d00"), Gravity = 80 }, 24); } _particles.Update(dt);}Updateruns at the fixed rate;dtis always 1/60 of a second by default.- Input is read by action name, never by key.
Axis("left", "right")returns -1, 0 or 1. The defaultInputMapbindsleft/right/up/downto arrows, WASD, the d-pad and the left stick, andconfirmto Z, Space, Enter, J and pad A. Pressedis true for exactly one update per press.pitchJittervaries each play slightly so repeated sounds do not feel mechanical.
Draw
public override void Draw(IRenderer r){ Font.DrawCentered(r, "Hello, MicroEngine!", new Vector2(160, 40), Color.Hex("fff1e8"), 2, Color.Hex("000000")); Font.DrawCentered(r, "Arrows move · Z/Space bursts", new Vector2(160, 160), Color.Hex("c2c3c7")); _particles.Draw(r); r.Draw(game.Atlas["star"], _position + new Vector2(0, MathX.Wave(Age, 1.5f, 2)));}Drawing is immediate-mode in virtual pixels (320x180 here). The built-in font needs no asset. Age is the
seconds this scene has been updated, and MathX.Wave turns it into a gentle bob. The backend scales the canvas
to the window by whole factors and letterboxes it.
5. A scripted smoke run
samples/HelloEngine/hello.script drives the same game without a
person:
# Scripted smoke run used by docs and CI20 hold right 3060 press confirm64 capture hello.png70 quitStarted with --script hello.script --hidden --mute --captures captures, the desktop launcher plays it in a hidden
window without sound and writes hello.png to captures/.
Each line is an update number and a command; the script forces actions through the same InputMap the game
reads. See Testing.
Where next
- Making a game grows this into a full game step by step.
- Usage patterns shows how the four games organise the same pieces at scale.
- Lifecycle and Scenes explain the loop and the stack.