A WebGPU retro game engine for TypeScript, inspired by RetroBlit. Build pixel-perfect 2D games with a clean, fantasy-console-style API.
blit-tech docs api-assets.md
6.5 kB · 163 lines
Markdown
at main

API: Assets #

Sprite sheets, bitmap fonts, and asset loading.


Asset size limits #

Sprite sheets, font atlases, and raw indexed buffers share the same decoded-size policy as render configuration (8192 pixels per side, 16,777,216 total pixels). Limits are enforced before canvas readback, CPU buffer retention, GPU texture creation, and software sprite loops.

Limit Default Applies to
Max width / height 8192 Decoded PNGs, font atlas textures, fromIndexedPixels()
Max total pixels 16,777,216 (4096 × 4096) Same sources
Max .btfont JSON size 1,048,576 bytes (1 MiB) BitmapFont.load() before JSON.parse()
Max embedded texture payload 524,288 bytes (512 KiB) Base64 data in texture when using data:image/png;base64,...
Max glyph count 8192 Glyph map entries in a .btfont file
Max software blit area 16,777,216 pixels Software renderer source rectangles (clipped to the sheet first)

When a limit is exceeded, loading throws an AssetLimitError with a beginner-friendly message. The software renderer skips sprite blits whose source rectangle is empty, non-integer, fully outside the sheet, or still too large after clipping.

.btfont files may reference either a relative PNG path or an embedded PNG data URI. Embedded textures must use data:image/png;base64,... and stay within the embedded payload cap above. Other data: schemes (for example JPEG) are rejected before image decode. Decoded atlas dimensions use the same width, height, and pixel-area limits as sprite sheets. Prefer separate PNG files for large atlases so the JSON payload stays under the JSON size limit.


Loading Assets #

AssetLoader caches images by URL so repeated loads share the same HTMLImageElement. Oversized images are rejected as soon as the browser reports decoded dimensions.

import { AssetLoader } from 'blit-tech';

// Load multiple images in parallel
const images = await AssetLoader.loadImages(['sprites.png', 'tiles.png']);

// Check cache before loading
if (AssetLoader.isLoaded('sprites.png')) {
  // already cached
}

Sprite Setup - Preferred Path #

Use SpriteSheet.loadIndexed() for all standard sprite setup. It combines color registration, image loading, and palette indexization in one call.

import { SpriteSheet, Palette } from 'blit-tech';

const palette = new Palette(256);

const indexed = await SpriteSheet.loadIndexed(
  'sprites/hero.png', // URL
  palette, // palette to populate
  10, // startSlot - first palette slot to write colors into
  { sort: 'luminance' }, // optional: color order in palette ('luminance' | 'none')
);

BT.paletteSet(palette); // activate AFTER loadIndexed returns

// Draw using the returned sheet and source rectangle:
BT.drawSprite(indexed.sheet, indexed.srcRect, new Vector2i(20, 20));

// indexed.colors - list of Color32 values registered into the palette
// indexed.srcRect - Rect2i spanning the full image

Colors are sorted by perceived luminance (darkest-first) by default. Pass { sort: 'none' } to preserve row-major scan order. Slot 0 is never touched - transparent pixels in the image map to slot 0 at draw time.


Sprite Setup - Manual Path #

Use this only when you need fine-grained control over the palette layout or want to load several sheets into the same palette sequentially.

// Step 1: register colors from each image into the palette
const colors = await SpriteSheet.loadColorsIntoPalette('hero.png', palette, 10);
const tileColors = await SpriteSheet.loadColorsIntoPalette('tiles.png', palette, 10 + colors.length);

// Step 2: load the image into a SpriteSheet
const sheet = await SpriteSheet.load('hero.png');

// Step 3: convert RGBA pixels to palette indices
sheet.indexize(palette);

BT.paletteSet(palette);

To create a sheet from raw palette-indexed pixel data (advanced / test use):

const sheet = SpriteSheet.fromIndexedPixels(width, height, indexedPixels);

Palette Offset #

Pass a paletteOffset to BT.drawSprite() to shift the entire sprite's color range by N slots. Useful for team-color variations and damage flashes. Full semantics in API: Rendering.

BT.drawSprite(sheet, srcRect, pos, 16); // render in "blue team" color range

Bitmap Fonts #

Load .btfont files for proportional, palette-indexed bitmap fonts.

import { BitmapFont } from 'blit-tech';

const font = await BitmapFont.load('fonts/MyFont.btfont');
BT.printFont(font, new Vector2i(10, 10), 'Hello!');
BT.printFont(font, new Vector2i(10, 10), 'Hello!', paletteOffset); // tinted variant

The font's internal sprite sheet is indexized automatically when loaded. Font rendering goes through the same sprite pipeline as BT.drawSprite() and is auto-batched.

See Bitmap Fonts Guide for the .btfont format specification and the BMFont conversion workflow (pnpm convert-font).


System Font #

A built-in 6×14 monospace font covering printable ASCII (characters 32-126). No load step needed.

BT.systemPrint(new Vector2i(10, 10), paletteIndex, 'Score: 100');
BT.systemPrintMeasure('Score: 100'); // → Vector2i (pixel width, height)

Use BT.systemPrint() for debug overlays and simple HUDs. For styled variable-width text, use a bitmap font instead.


See Also #

Guide What it covers
API: Core bootstrap, init, game loop, core types
API: Rendering primitives, sprites, text, post-process
API: Palette palette setup, presets, effects
Palette Guide palette-first setup, offsets, refresh
Palette Presets built-in preset reference
Bitmap Fonts .btfont format, BMFont conversion