Skip to content

Assets and content

MicroEngine is code-first: sprites, tiles, fonts, sounds and music can all be generated in C# at start-up, so a game can ship without a single binary file. When a game wants existing art or audio, it keeps the files under its own Content/ folder and loads them through ContentFolder with managed PNG and WAV decoders, while OGG and MP3 music is streamed by the backend. Both approaches can be mixed per element, and every shipped file is credited in the game’s CREDITS.md.

Choosing an approach

Approach Example What ships
Fully procedural Meadow Run Code only: PixelImage art, Synth sounds, Song music
Hybrid Courtyard Key, Trail Duel Mostly code, plus a few CC0 sprites or jingles repainted or blended in
File-based Neon Rift CC0 sprite sheets, tilesets, WAV effects and OGG music

The reasoning is recorded in ADR 0002 (code-first default), ADR 0004 (external files) and ADR 0005 (hybrid games). Authoring art in code is covered in Rendering and sound in Audio.

Shipping a Content folder

Keep files in games/<Name>/Content/ and copy them next to the executable at build time:

<ItemGroup>
<None Include="Content/**" CopyToOutputDirectory="PreserveNewest" LinkBase="Content" />
</ItemGroup>

Source: games/NeonRift/NeonRift.csproj

Some games also keep C# level definitions under Content/ (for example games/NeonRift/Content/Stages.cs); they compile as normal code, and the web build leaves .cs files out of the package.

ContentFolder

public sealed class ContentFolder
{
public string Root { get; }
public ContentFolder(string? root = null)
{
Root = Path.GetFullPath(root ?? Path.Combine(AppContext.BaseDirectory, "Content"));
if (!Directory.Exists(Root)) throw new DirectoryNotFoundException($"Content folder not found: {Root}");
}
// ...
public bool Exists(string relative) => File.Exists(Path.Combine(Root, relative.Replace('/', Path.DirectorySeparatorChar)));
public byte[] ReadBytes(string relative) => File.ReadAllBytes(PathOf(relative));
public Graphics.PixelImage Image(string relative) => Graphics.PixelImage.Load(PathOf(relative));
}

Source: src/MicroEngine/Core/ContentFolder.cs

Member Behaviour
new ContentFolder(root?) Default root is <exe dir>/Content; a missing folder throws with the full path
PathOf("sfx/shot.wav") Full path from a /-separated relative path; throws if missing or outside the root
Image(relative) Loads a PNG as a PixelImage
ReadBytes(relative), Exists(relative) Raw access

Games accept an optional root so tests can point at another folder (new RiftGame(..., contentRoot: ...)). In a browser the page copies the package’s files into the runtime’s virtual file system at /Content, so the same code works unchanged (web builds).

Images

PixelImage.Load(path) and PixelImage.FromPng(bytes) decode PNG in managed code: 8-bit greyscale, greyscale with alpha, RGB and RGBA, and 1/2/4/8-bit paletted images with tRNS transparency, non-interlaced. Other variants (16-bit channels, interlaced files) are rejected; Load names the file in the error. Loaded images are ordinary PixelImages, so they can be cropped, recoloured, rotated or silhouetted before packing.

Grid sheets

SpriteAtlasBuilder.AddGrid(name, sheet, cellWidth, cellHeight, count?, origin?) slices a row-major sheet into frames name0, name1, …; without count, fully transparent trailing cells of the last row are dropped.

// Hero (Warped City): every strip shares the 71×67 canvas and the feet pivot.
foreach (var name in new[] { "idle", "run", "run-shoot", "jump", "back-jump", "crouch", "shoot", "hurt" })
b.AddGrid("hero_" + name, content.Image($"hero/{name}.png"), 71, 67, origin: HeroOrigin);

Source: games/NeonRift/Art/Assets.cs

Repainting imported art

Hybrid games repaint imported sprites with their own palette at load so they match the procedural art:

private static PixelImage Repaint(PixelImage sheet, params (string From, Color To)[] swaps)
{
foreach (var (from, to) in swaps) sheet.Recolor(Color.Hex(from), to);
return sheet.Recolor(Color.Hex("141b1b"), Pal.Ink);
}

Source: games/CourtyardKey/Visuals/MonsterArt.cs

Audio files

AudioMixer.AddSoundFile decodes PCM WAV (8/16/24-bit, mono or stereo). AddMusicFile decodes WAV the same way and hands any other extension, such as .ogg or .mp3, to the device to stream. See Audio.

Credits convention

Every game that ships files lists them in games/<Name>/CREDITS.md: which files come from which pack, author, source URL, licence, the date the licence was checked, and any changes made (joined strips, downmixed tracks). All shipped assets today are CC0. Examples: Neon Rift, Courtyard Key, Trail Duel. Meadow Run ships no files and has no credits file.

Limitations

  • No asset pipeline, hot reload or content packing: files are read directly at load time.
  • Supported formats are PNG (images), WAV (sounds and music), and OGG/MP3 (music only).
  • No importers for map editors, Aseprite files or texture packer layouts; slicing is grid-based or done in code.