Images & drawing
An image is a grid of palette indices; a palette (u32[]) maps indices to 0x00RRGGBB colors. Palette index 0 is always transparent. All drawing is client-side.
Constructing images
A Munos mod ships as one self-contained file, so every image is inlined as data in the source.
image_literal
image_literal(w: i32, h: i32, data: string): imageBuilds a w × h image from base64-encoded palette indices (one byte per pixel, row-major), decoded at compile time. Good for simple/hand-built art.
var block: image = image_literal(32, 32, "AQEBAQEB…")image_from_bytes
image_from_bytes(data: u8[]): imageBuilds an image from a byte stream whose first byte is width, second byte is height, and remaining bytes are pixel indices in row-major order. Useful when image data arrives over the network (from event receive).
image_from_bitmap_bytes · client
image_from_bitmap_bytes(data: u8[], dx: i32, dy: i32): imageDecodes a compact indexed-bitmap blob (the format carries its own width, height, and bit depth in a 3-byte header) into an image. Preferred for sprites — a few times smaller than PNG for low-color art, with no decoder overhead at runtime.
dx / dy are a per-image alignment nudge added to the draw position every time this image is drawn — use them to keep an animation's anchor steady as frame bounding-boxes shift. Pass 0, 0 when not needed. Under a flip the nudge is negated automatically so one tuned value stays correct in both facings.
var bytes: u8[] = base64_decode("FRgD…")
var sprite: image = image_from_bitmap_bytes(bytes, 0, 0)image_from_png_bytes · client
image_from_png_bytes(data: u8[], x: i32, y: i32, w: i32, h: i32): imageDecodes a PNG blob and takes the (x, y, w, h) sub-rectangle as a palette-indexed image — ideal for slicing one frame from a sprite sheet. The palette is generated automatically: pixels with alpha < 128 become index 0 (transparent); opaque colors are sorted by luminance. Every slice of the same data shares one palette.
palette_from_png_bytes · client
palette_from_png_bytes(data: u8[]): u32[]Returns the auto-generated palette for a PNG blob (slot 0 transparent). Pair with image_from_png_bytes.
var bytes: u8[] = base64_decode("iVBORw0K…")
var sprite: image = image_from_png_bytes(bytes, 0, 0, 16, 16)
var pal: u32[] = palette_from_png_bytes(bytes)base64_decode
All three byte-based loaders pair with base64_decode(s: string): u8[] to inline a binary asset directly in the .munos source. See Networking & packing.
Drawing
draw_image(img: image, pal: u32[], x: i32, y: i32,
flip_x: bool = false, flip_y: bool = false,
clip_x: i32 = 0, clip_y: i32 = 0, clip_w: i32 = -1, clip_h: i32 = -1,
clip_rect_x1: i32 = -1, clip_rect_y1: i32 = -1,
clip_rect_x2: i32 = -1, clip_rect_y2: i32 = -1)Client-side. Paints img with its top-left at screen (x, y), resolving indices through pal. Index-0 pixels are skipped; an out-of-range index is skipped too.
The common call is just the first four arguments:
draw_image(sprite, pal, x, y)Flipping
flip_x / flip_y mirror the image horizontally / vertically.
draw_image(sprite, pal, x, y, flip_x = true)Source-space clip (clip_x/y/w/h)
Picks a sub-rectangle of the image to draw. clip_w = -1 / clip_h = -1 mean "use the full remaining width/height from clip_x/clip_y."
// draw only the 16×16 top-left tile of a larger sheet image
draw_image(sheet, pal, x, y, clip_x = 0, clip_y = 0, clip_w = 16, clip_h = 16)Screen-space scissor (clip_rect_x1/y1/x2/y2)
A screen rectangle outside which no pixel is drawn. Any pixel landing outside [clip_rect_x1, clip_rect_x2) × [clip_rect_y1, clip_rect_y2) is suppressed. Each side defaults to -1 = "unbounded on this side," so you specify only the edges you need.
// keep a ghost below a 32px-tall HUD strip at the top of the screen
draw_image(ghost, pal, gx, gy, clip_rect_y1 = 32)The two clips are independent: source-space chooses what part of the image to read; screen-space chooses where on screen it's allowed to land.
Palette swap
Because the palette is a separate argument, the same image draws in different colors with a different palette — recoloring is free.
draw_image(player, marioPal, 100, 100) // red
draw_image(player, luigiPal, 140, 100) // green, identical pixels