/**
 * Bitmap Font Demo - load a proportional .btfont and compare it to the built-in system font.
 * @description Load a proportional .btfont file and draw rainbow, alpha-pulsing, and measured text with it.
 *
 * Part of the BLIT386 demo series.
 * Prerequisites:
 *   Basics  https://demos.blit386.dev/basics
 *   Fonts   https://demos.blit386.dev/fonts
 *
 * Live version: https://demos.blit386.dev/bitmap-font
 *
 * Earlier demos use BT.systemPrint() - the built-in 6x14 pixel system font that needs no file.
 * This demo shows the ALTERNATIVE: loading a proportional bitmap font from a .btfont file.
 *
 * A "bitmap font" is a font where every letter is pre-drawn as a small picture
 * (a grid of pixels), rather than being drawn from mathematical curves.
 * This gives text a crisp, retro look that matches pixel art perfectly.
 *
 * When would you choose a bitmap font over the system font?
 *   - You want a proportional font (each letter has its own width, like real typography).
 *   - You need a specific visual style (blocky, cursive, monospace, etc.).
 *   - You want fine control over per-character color effects (like the rainbow below).
 *   - You need to measure text width precisely before drawing it (font.measureText()).
 *
 * When should you stick with BT.systemPrint()?
 *   - You just need a quick debug overlay (FPS, position, counters).
 *   - You don't want the extra complexity of loading a font asset.
 *   - Startup speed matters more than visual style.
 *
 * This demo shows how to load a font, draw text in different colors,
 * make text that changes color over time (rainbow), text that pulses in opacity (alpha),
 * and how to measure how wide a piece of text will be before drawing it.
 *
 * The font-metadata caption in the bottom-right corner is drawn with the shared demo UI kit
 * (src/shared/ui.js), so it looks the same as the info panels in every other demo. The
 * showcase lines themselves are hand-drawn on purpose - they ARE the lesson.
 */

import { 
type BitmapFont = BitmapFont
class BitmapFont
Bitmap font backed by a sprite-sheet texture atlas. The class is responsible for: - loading `.btfont` metadata and its referenced texture - exposing glyph lookup by character or character code - measuring string widths with a small reusable cache - providing the underlying {@link SpriteSheet } used for rendering glyph quads
@since0.1.0@changed1.5.0 `getGlyph` / `getGlyphByCode` (and `measureText`, which now shares their lookup) substitute a font-defined fallback glyph for a missing character instead of returning `null`, when the font's glyph map has an entry keyed by `U+FFFD`.@changed1.7.0 Added the `codePoints` getter, returning every Unicode code point the font defines a glyph for (ascending, derived live from the same glyph map `getGlyph()` and `hasGlyph()` read).
BitmapFont
, function bootstrap(DemoClass: DemoConstructor, options?: BootstrapOptions): Promise<boolean>
One-liner bootstrap function for BLIT386 demos. Handles canvas retrieval and engine initialization. Backend selection (WebGPU or software fallback) is managed internally by BTAPI. This function provides a streamlined way to start a demo with sensible defaults while allowing customization through options.
@since0.2.0@changed1.4.0 Calling `bootstrap()` again while already initialized now routes to a hot swap (via {@link registerHotReload}) when a Vite HMR context is registered, or logs a double-bootstrap guard and returns `false` otherwise - previously it silently started a second, unstoppable `GameLoop`.@changed1.7.0 Exposes `BT` on `window.BT` after bootstrap finishes, gated by {@link BootstrapOptions.exposeGlobal} (default: {@link BT.isDevMode}).@paramDemoClass - Demo class constructor implementing `IBTDemo` (optional `configure()` for hardware settings).@paramoptions - Optional configuration for IDs and callbacks.@returns`true` when the demo boots successfully; otherwise `false`.@example// Simplest usage - uses default IDs. bootstrap(MyDemo);@example// With custom options. bootstrap(MyDemo, { canvasID: 'custom-canvas', containerID: 'custom-container', onSuccess: () => console.log('Demo started!'), onError: (err) => analytics.trackError(err), });@example// Await the result. const success = await bootstrap(MyDemo); if (success) { console.log('Demo is running'); }
bootstrap
,
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
, class Color32
Mutable 32-bit RGBA color value with 8-bit channels.
@since0.1.0
Color32
, class Vector2i
Integer 2D vector for pixel-perfect positioning. Used for points, sizes, directions, and camera offsets throughout the engine. The API includes both allocation-free `*To()` / `*InPlace()` variants and convenience methods that return new vectors.
@since0.1.0
Vector2i
} from 'blit386';
// The shared demo UI kit. applyTheme() installs the kit's twelve UI colors high in the // palette (slots 240-251, far above this demo's slots 1-38), and ui.* draws the small // "Font Info" panel in the bottom-right corner of the screen. import { import applyThemeapplyTheme, import uiui, import UI_ANCHORSUI_ANCHORS } from './shared/ui.js'; /** @typedef {import('blit386').IBTDemo} IBTDemo */ /** @typedef {import('blit386').Palette} Palette */ /** @typedef {import('blit386').BitmapFont} BitmapFont */ // The x position where the rainbow text row starts. // Shared by update() (hue calculation) and renderRainbowText() (glyph drawing) so they stay in sync. const const RAINBOW_ORIGIN_X: 10RAINBOW_ORIGIN_X = 10; // Every color used for drawing is stored in a numbered palette slot. // Index 0 is always transparent. Custom colors start at 1. // The screen background and the Font Info panel use the shared UI theme instead // (installed by applyTheme() in init()), so there are no background slots here. const const C_WHITE: 1C_WHITE = 1; // Pure white: title, special characters, 'A'/'B' labels const const C_RED_TEXT: 3C_RED_TEXT = 3; // Soft red: "Red Text" sample line const const C_GREEN_TEXT: 4C_GREEN_TEXT = 4; // Soft green: "Green Text" sample line const const C_BLUE_TEXT: 5C_BLUE_TEXT = 5; // Soft blue: "Blue Text" sample line const const C_YELLOW_TEXT: 6C_YELLOW_TEXT = 6; // Yellow: "Yellow Text" sample line const const C_GRAY_TEXT: 7C_GRAY_TEXT = 7; // Light gray: "Measured Width" text const const C_ORANGE_LINE: 8C_ORANGE_LINE = 8; // Orange: underline below the measured-width text // We define the rainbow text string before the slot constants so C_PULSE can be derived from it. // If you change this string, update() will compute the right number of palette colors automatically. const const RAINBOW_TEXT: "Rainbow Animation!"RAINBOW_TEXT = 'Rainbow Animation!'; // Dynamic slots: each character in RAINBOW_TEXT gets its own animated color slot. // We start at C_RAINBOW_BASE and reserve one slot per character. // update() computes each character's current hue and stores it here. // render() then reads the slot index - no Color32 math happens during drawing! const const C_RAINBOW_BASE: 20C_RAINBOW_BASE = 20; // first slot for the rainbow characters // Dynamic slot: placed immediately after the rainbow slots so it can never overlap them // even if RAINBOW_TEXT changes length. C_PULSE = C_RAINBOW_BASE + RAINBOW_TEXT.length. const const C_PULSE: anyC_PULSE = const C_RAINBOW_BASE: 20C_RAINBOW_BASE + const RAINBOW_TEXT: "Rainbow Animation!"RAINBOW_TEXT.length; // single slot for the pulsing-text color // Left margin for labels and body text (filled in init() for the gap after "A: " / "B: "). const const LABEL_X: 10LABEL_X = 10; /** * Demonstrates bitmap font loading and rendering with various text effects. * Shows static colors, animated rainbow effects, text measurement, and font metadata. * Contrast this approach with BT.systemPrint() used in the Fonts demo. * * @implements {IBTDemo} */ class class Demo
Demonstrates bitmap font loading and rendering with various text effects. Shows static colors, animated rainbow effects, text measurement, and font metadata. Contrast this approach with BT.systemPrint() used in the Fonts demo.
@implementsIBTDemo
Demo
{
// font will hold the loaded bitmap font once it is downloaded. // It starts as null because nothing is loaded yet. /** @type {BitmapFont | null} */ Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
= null;
// palette holds all the colors this demo uses. /** @type {Palette | null} */ Demo.palette: Palette | null
@type{Palette | null}
palette
= null;
// theme holds the palette slot numbers of the shared UI kit colors, filled in by // applyTheme() in init(). We use theme.bg to clear the screen so this demo's // background matches every other demo in the series. Demo.theme: nulltheme = null; // animTime is a timer that counts up in seconds. // We use it to control the speed of color animations. Demo.animTime: numberanimTime = 0; // Measured in init() from BT.systemPrintMeasure('M') - built-in system font is 6x14. Demo.systemCharWidth: numbersystemCharWidth = 6; Demo.systemLineHeight: numbersystemLineHeight = 14; // Pixel width of the "A: " prefix so title text lines up after the label. Demo.labelPrefixWidth: numberlabelPrefixWidth = 18; /** * Sets up the color palette and downloads the bitmap font. * Screen size and FPS use engine defaultConfig() (no configure() in this demo). * Notice the "await" keyword - we wait here until the font file is fully downloaded. * The built-in system font (BT.systemPrint) skips this step entirely. * Returns true when the font has loaded successfully, or false if loading fails. * * @returns {Promise<boolean>} */ async Demo.init(): Promise<boolean>
Sets up the color palette and downloads the bitmap font. Screen size and FPS use engine defaultConfig() (no configure() in this demo). Notice the "await" keyword - we wait here until the font file is fully downloaded. The built-in system font (BT.systemPrint) skips this step entirely. Returns true when the font has loaded successfully, or false if loading fails.
@returns
init
() {
console.log('[BitmapFontDemo] Initializing...'); // Set up the color palette // We pick every color before drawing anything, like an artist mixing paint. this.Demo.palette: Palette | null
@type{Palette | null}
palette
=
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.paletteCreate: (size?: number) => Palette
Creates a standalone palette instance.
@since1.0.3@paramsize - Palette size. Defaults to 256 colors.@returnsNew mutable palette.
paletteCreate
(256);
// Static colors that never change from frame to frame. this.Demo.palette: Palette
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_WHITE: 1C_WHITE, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(255, 255, 255)); // pure white
this.Demo.palette: Palette
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_RED_TEXT: 3C_RED_TEXT, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(255, 100, 100)); // soft red
this.Demo.palette: Palette
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_GREEN_TEXT: 4C_GREEN_TEXT, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(100, 255, 100)); // soft green
this.Demo.palette: Palette
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_BLUE_TEXT: 5C_BLUE_TEXT, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(100, 100, 255)); // soft blue
this.Demo.palette: Palette
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_YELLOW_TEXT: 6C_YELLOW_TEXT, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(255, 255, 100)); // yellow
this.Demo.palette: Palette
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_GRAY_TEXT: 7C_GRAY_TEXT, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(200, 200, 200)); // light gray
this.Demo.palette: Palette
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_ORANGE_LINE: 8C_ORANGE_LINE, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(255, 200, 100)); // orange for underlines
// Pre-fill dynamic rainbow slots with gray so they're not empty on the first frame. for (let let i: numberi = 0; let i: numberi < const RAINBOW_TEXT: "Rainbow Animation!"RAINBOW_TEXT.length; let i: numberi++) { this.Demo.palette: Palette
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_RAINBOW_BASE: 20C_RAINBOW_BASE + let i: numberi, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(128, 128, 128));
} // Pre-fill pulse slot. this.Demo.palette: Palette
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_PULSE: anyC_PULSE, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(100, 100, 255));
// Install the shared UI kit colors. They land in palette slots 240-251, well above // this demo's highest slot (C_PULSE = 38), so the two can never collide. The // returned map remembers which slot each UI color went to (theme.bg, theme.text, ...). this.Demo.theme: nulltheme = import applyThemeapplyTheme(this.Demo.palette: Palette
@type{Palette | null}
palette
);
// Tell the engine to use this palette for all drawing.
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.paletteSet: (palette: Palette) => void
Stores the active engine palette. Use this to swap the **entire palette** (e.g. switch between a day and night theme). After this call the renderer uploads the new palette uniform on the next frame. **Palette-value swap (change what a slot looks like):** mutate the live {@link BT.palette } in place with `palette.set(slot, newColor)`. The renderer uploads dirty slots on the next frame; no `paletteSet()` or {@link BT.spritesRefresh } needed. **Palette-layout swap (same colors, different slot positions):** build a new palette with the same colors at new indices, call `paletteSet()`, then call {@link BT.spritesRefresh } so every sprite sheet re-maps its original RGBA pixels against the new slot layout.
@since1.0.3@parampalette - Palette to make active.
paletteSet
(this.Demo.palette: Palette
@type{Palette | null}
palette
);
// Measure the built-in system font once (same helper as demo fonts). const const glyphSize: Vector2iglyphSize =
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.systemPrintMeasure: (text: string) => Vector2i
Measures the pixel dimensions of a string rendered with the built-in system font.
@since1.0.3@paramtext - Text string to measure.@returnsWidth and height in pixels, or `Vector2i.zero()` before engine initialization.
systemPrintMeasure
('M');
this.Demo.systemCharWidth: numbersystemCharWidth = const glyphSize: Vector2iglyphSize.Vector2i.x: number
Horizontal component (defaults to 0).
x
;
this.Demo.systemLineHeight: numbersystemLineHeight = const glyphSize: Vector2iglyphSize.Vector2i.y: number
Vertical component (defaults to 0).
y
;
this.Demo.labelPrefixWidth: numberlabelPrefixWidth =
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.systemPrintMeasure: (text: string) => Vector2i
Measures the pixel dimensions of a string rendered with the built-in system font.
@since1.0.3@paramtext - Text string to measure.@returnsWidth and height in pixels, or `Vector2i.zero()` before engine initialization.
systemPrintMeasure
('A: ').Vector2i.x: number
Horizontal component (defaults to 0).
x
;
// Load the font file from the server. // .btfont is BLIT386's custom font format that includes glyph images. // This is the step that BT.systemPrint() skips - the system font is built in. try { this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
= await class BitmapFont
Bitmap font backed by a sprite-sheet texture atlas. The class is responsible for: - loading `.btfont` metadata and its referenced texture - exposing glyph lookup by character or character code - measuring string widths with a small reusable cache - providing the underlying {@link SpriteSheet } used for rendering glyph quads
@since0.1.0@changed1.5.0 `getGlyph` / `getGlyphByCode` (and `measureText`, which now shares their lookup) substitute a font-defined fallback glyph for a missing character instead of returning `null`, when the font's glyph map has an entry keyed by `U+FFFD`.@changed1.7.0 Added the `codePoints` getter, returning every Unicode code point the font defines a glyph for (ascending, derived live from the same glyph map `getGlyph()` and `hasGlyph()` read).
BitmapFont
.BitmapFont.load(url: string): Promise<BitmapFont>
Loads a bitmap font from a `.btfont` JSON file. The font descriptor can reference either an embedded PNG data URI (`data:image/png;base64,...`) or a texture file path relative to the font JSON file.
@paramurl - Path to the .btfont file.@returnsLoaded bitmap font instance.@throwsError if the font descriptor or texture cannot be loaded.
load
('/fonts/PragmataPro14.btfont');
// The font object exposes useful metadata you can read and display. console.log(`[BitmapFontDemo] Loaded font: ${this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.name: string
Font display name.
name
}`);
console.log(` Size: ${this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.size: number
Original font size in points.
size
}pt`);
console.log(` Line height: ${this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.lineHeight: number
Pixels between baselines for multi-line text.
lineHeight
}px`);
console.log(` Glyphs: ${this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.glyphCount: number
Returns the total number of glyphs loaded into the font.
@returnsTotal glyph count.
glyphCount
}`);
} catch (function (local var) error: unknownerror) { console.error('[BitmapFontDemo] Failed to load font:', function (local var) error: unknownerror); return false; } // Tell the font about our palette. Font glyphs are stored as white pixels in the // font's sprite sheet. indexize() maps those white pixels to palette slot C_WHITE (1). // After this call, BT.printFont() can recolor the glyphs by shifting the palette index. this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.getSpriteSheet(): SpriteSheet
Returns the sprite sheet that owns the font texture atlas.
@returnsSprite sheet used when rendering glyph quads.
getSpriteSheet
().SpriteSheet.indexize(palette: Palette): void
Converts the sprite sheet's RGBA pixels to palette indices. Each non-transparent pixel is looked up in the provided palette via exact color matching. Index 0 is always transparent. The resulting indices are stored internally; an `r8uint` GPU texture is created lazily on the next `getTexture()` call. The original RGBA data is retained so `reindexize()` can re-convert after a palette swap without reloading the image.
@parampalette - Active palette used for color-to-index mapping.@throwsIf any opaque pixel's color is not present in the palette.
indexize
(this.Demo.palette: Palette
@type{Palette | null}
palette
);
console.log('[BitmapFontDemo] Font loaded successfully!'); return true; } // Runs at a fixed rate (60 times per second). // We learned about the demo loop in the Basics demo: https://demos.blit386.dev/basics // We advance the animation timer AND update dynamic palette colors here. Demo.update(): void
Called zero or more times per frame at the fixed timestep declared by `targetFPS`. The accumulator pattern ensures the target rate is met on average, but a single frame may invoke this multiple times (catch-up) or not at all. Update simulation, timers, and input-driven state here. This is a hot path. Minimize allocations, reuse objects, and prefer in-place vector operations where possible. Avoid rendering work here; draw in `render()` instead.
update
() {
// Move the animation clock forward by one fixed update step in seconds. this.Demo.animTime: numberanimTime +=
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.deltaSeconds: number
Fixed-step seconds per update tick. Equivalent to `1 / BT.targetFPS` when `BT.targetFPS` is finite and positive. Falls back to `1 / 60` when target FPS is non-finite or non-positive.
@since1.0.4@returnsSeconds advanced by one fixed update tick.
deltaSeconds
;
// Update the pulsing text color // Math.sin returns a wave that smoothly oscillates between -1 and +1. // The formula "2 * Math.PI * frequency" converts seconds into radians, which is what // Math.sin expects. With frequency=3 the wave completes exactly 3 full cycles per second. // Multiplying by 0.5 and adding 0.5 shifts the output from [-1,1] to [0,1]. const const pulse: numberpulse = Math.sin(2 * Math.PI * 3 * this.Demo.animTime: numberanimTime) * 0.5 + 0.5; // The alpha channel controls how opaque (visible) the text is. // At pulse=0 the text is nearly invisible; at pulse=1 it is fully opaque. // RGB stays fixed at (100, 100, 255) - a medium blue - so only opacity changes. this.Demo.palette: Palette | null
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_PULSE: anyC_PULSE, new new Color32(r?: number, g?: number, b?: number, a?: number): Color32
Creates a clamped 8-bit RGBA color.
@paramr - Red channel (0-255, defaults to 255).@paramg - Green channel (0-255, defaults to 255).@paramb - Blue channel (0-255, defaults to 255).@parama - Alpha channel (0-255, defaults to 255 = opaque).
Color32
(100, 100, 255, Math.floor(const pulse: numberpulse * 255)));
// Update the rainbow text character colors // We compute hue (color wheel position) for each character based on its x position // and animTime. The font is always loaded here: the demo loop only starts after // init() finished successfully, and init() returns false when the font fails. // We learned about HSL (Hue, Saturation, Lightness) colors in the Colors demo: // https://demos.blit386.dev/colors let let charX: numbercharX = const RAINBOW_ORIGIN_X: 10RAINBOW_ORIGIN_X; // Starting x position - same as where render() draws the rainbow text. for (let let i: numberi = 0; let i: numberi < const RAINBOW_TEXT: "Rainbow Animation!"RAINBOW_TEXT.length; let i: numberi++) { // hue is a position on the color wheel (0=red, 120=green, 240=blue, 360=back to red). // Using charX (actual x position) matches the visual rhythm of the rainbow. // Adding animTime*100 scrolls the rainbow to the left over time. // The % 360 keeps hue within the 0-359 range so it cycles smoothly around the // color wheel instead of growing unbounded as animTime increases. const const hue: numberhue = (let charX: numbercharX * 3 + this.Demo.animTime: numberanimTime * 100) % 360; this.Demo.palette: Palette | null
@type{Palette | null}
palette
.Palette.set(index: number, color: Color32): void
Writes a color into a palette slot.
@paramindex - Palette index to overwrite.@paramcolor - Color to store.@throwsError if the index is invalid or if index `0` is set opaque.
set
(const C_RAINBOW_BASE: 20C_RAINBOW_BASE + let i: numberi, class Color32
Mutable 32-bit RGBA color value with 8-bit channels.
@since0.1.0
Color32
.Color32.fromHSL(h: number, s: number, l: number, a?: number): Color32
Creates a color from HSL values.
@paramh - Hue in degrees (0-360).@params - Saturation as percentage (0-100).@paraml - Lightness as percentage (0-100).@parama - Alpha channel (0-255, defaults to 255).@returnsNew color converted from HSL values.
fromHSL
(const hue: numberhue, 100, 60));
// Advance charX by this character's actual pixel width in the font. // This is specific to BitmapFont - the system font advances a fixed systemCharWidth per character. const const glyph: Glyph | nullglyph = this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.getGlyph(char: string): Glyph | null
Returns glyph data for a character. Uses the ASCII lookup table for single-byte characters and falls back to the Unicode glyph map for everything else, then to the font's fallback glyph (see {@link FALLBACK_GLYPH_CHAR } ) when neither has an entry for the character.
@paramchar - Single character to look up (supports Unicode).@returnsGlyph metadata; the font's fallback glyph when the character is missing and a fallback is defined; otherwise `null`.
getGlyph
(const RAINBOW_TEXT: "Rainbow Animation!"RAINBOW_TEXT[let i: numberi]);
let charX: numbercharX += const glyph: Glyph | nullglyph ? const glyph: Glyphglyph.Glyph.advance: number
Horizontal advance after drawing (distance to next character).
advance
: 7;
} } // Runs once per screen refresh to draw all the text demonstrations on screen. Demo.render(): void
Called once per `requestAnimationFrame` tick (browser refresh rate). Issue all draw calls for the current frame here. When {@link HardwareSettings.isOverlayEnabled } is `true` (default), the engine draws a screen-space overlay HUD after this method returns (present FPS, target FPS, draw calls, frame/update()/render() timings, backend, demo title). Optional {@link overlayRows } adds stacked bars above the footer. Demos do not need to duplicate engine overlay text. Reserve about ~42 px at the top and space for the bottom palette grid (or ~13 px when {@link HardwareSettings.isOverlayPaletteEnabled } is `false`) at the bottom (plus ~14 px per custom overlay row) for overlay bars, or disable the overlay in `configure()` when using custom full-screen HUD layouts. This is a hot path. Batch draws by texture to reduce GPU state changes and reuse Color32/Vector2i instances instead of allocating per frame. Avoid mutating the simulation state here unless it is strictly visual.
render
() {
// Fill the screen with the shared UI theme's deep navy background.
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.clear: (paletteIndex: number) => void
Sets the frame clear color using a palette index. The renderer uses this color when clearing the full display at the start of the next frame.
@since0.1.0@parampaletteIndex - Palette index for the full-screen clear pass.
clear
(this.Demo.theme: nulltheme.bg);
// Start drawing from near the top of the screen. let let y: numbery = 10; // X where title text starts after the "A: " / "B: " labels (measured in init()). const const textX: numbertextX = const LABEL_X: 10LABEL_X + this.Demo.labelPrefixWidth: numberlabelPrefixWidth; // lineHeight tells us how many pixels tall one line of text is. // Bitmap font line height comes from the .btfont file; system font uses systemLineHeight. const const bitmapLineHeight: numberbitmapLineHeight = this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.lineHeight: number
Pixels between baselines for multi-line text.
lineHeight
+ 2;
const const systemLineHeight: numbersystemLineHeight = this.Demo.systemLineHeight: numbersystemLineHeight + 2; // BT.printFont() arguments: (font, position, text, colorOffset) // The colorOffset is a 0-based index FROM palette slot 1. // So offset 0 = slot 1 (C_WHITE), offset 2 = slot 3 (C_RED_TEXT), etc. // This is different from BT.systemPrint() which takes the palette slot number directly. // We learned about palette offset math in demo palette-presets and the palette guides. // Draw the title in both fonts, one below the other, so you can compare them side-by-side. // "A:" marks the bitmap font version (proportional spacing, each letter its own width). // "B:" marks the built-in system font (every character is a fixed 6x14 pixel block).
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.systemPrint: (pos: Vector2i, paletteIndex: number, text: string) => void
Draws text using the built-in 6x14 system font. The system font covers printable ASCII (characters 32-126). For custom bitmap fonts with proportional glyphs, use {@link BT.printFont } instead.
@since1.0.3@parampos - Text origin in display coordinates.@parampaletteIndex - Palette color index for the text.@paramtext - String to render.
systemPrint
(new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(const LABEL_X: 10LABEL_X, let y: numbery), const C_WHITE: 1C_WHITE, 'A:');
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.printFont: (font: BitmapFont, pos: Vector2i, text: string, paletteOffset?: number) => void
Draws text with a bitmap font through the indexed sprite pipeline. Supports proportional glyph widths and glyph-level offsets defined by the supplied {@link BitmapFont } . The font's underlying sprite sheet must have been indexized before calling this. Palette offset semantics and out-of-range behavior are identical to {@link BT.drawSprite } .
@since0.1.0@paramfont - Font asset used for rendering.@parampos - Text origin in display coordinates.@paramtext - String to render.@parampaletteOffset - Shift added to every stored glyph index before palette lookup (default 0).
printFont
(this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
, new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(const textX: numbertextX, let y: numbery), 'BLIT386 Bitmap Font Demo', 0);
let y: numbery += const bitmapLineHeight: numberbitmapLineHeight; // The same title text in the system font so the visual difference is obvious.
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.systemPrint: (pos: Vector2i, paletteIndex: number, text: string) => void
Draws text using the built-in 6x14 system font. The system font covers printable ASCII (characters 32-126). For custom bitmap fonts with proportional glyphs, use {@link BT.printFont } instead.
@since1.0.3@parampos - Text origin in display coordinates.@parampaletteIndex - Palette color index for the text.@paramtext - String to render.
systemPrint
(new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(const LABEL_X: 10LABEL_X, let y: numbery), const C_WHITE: 1C_WHITE, 'B:');
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.systemPrint: (pos: Vector2i, paletteIndex: number, text: string) => void
Draws text using the built-in 6x14 system font. The system font covers printable ASCII (characters 32-126). For custom bitmap fonts with proportional glyphs, use {@link BT.printFont } instead.
@since1.0.3@parampos - Text origin in display coordinates.@parampaletteIndex - Palette color index for the text.@paramtext - String to render.
systemPrint
(new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(const textX: numbertextX, let y: numbery), const C_WHITE: 1C_WHITE, 'BLIT386 Bitmap Font Demo');
// Move down past both title lines, with a little extra gap before the next section. let y: numbery += const systemLineHeight: numbersystemLineHeight + 4; // Draw each section in order, updating y as we go so nothing overlaps. let y: numbery = this.Demo.renderColoredText(y: any, lineHeight: any): anyrenderColoredText(let y: numbery, const bitmapLineHeight: numberbitmapLineHeight); let y: numbery = this.Demo.renderRainbowText(y: any, lineHeight: any): anyrenderRainbowText(let y: numbery, const bitmapLineHeight: numberbitmapLineHeight); let y: numbery = this.Demo.renderPulsingText(y: any, lineHeight: any): anyrenderPulsingText(let y: numbery, const bitmapLineHeight: numberbitmapLineHeight); let y: numbery = this.Demo.renderSpecialCharacters(y: any, lineHeight: any): anyrenderSpecialCharacters(let y: numbery, const bitmapLineHeight: numberbitmapLineHeight); this.Demo.renderTextMeasurement(y: any, lineHeight: any): anyrenderTextMeasurement(let y: numbery, const bitmapLineHeight: numberbitmapLineHeight); // Draw a small panel of font metadata (name, size, glyph count) in the bottom-right // corner using the shared UI kit. Measured FPS and the demo title are drawn by the // engine overlay. this.Demo.renderFontInfo(): voidrenderFontInfo(); } // Draws the same four words, each in a different color. // This shows how passing different palette offsets changes the text color. // Compare to BT.systemPrint() where you pass the palette slot directly. // y: the Y position to start drawing at. // lineHeight: how many pixels to move down between lines. // Returns the Y position after the last line drawn. Demo.renderColoredText(y: any, lineHeight: any): anyrenderColoredText(y: anyy, lineHeight: anylineHeight) { // Use a local variable so we don't modify the original parameter. // In JavaScript, changing a parameter's value inside a function can confuse readers // because they expect the original value to stay the same throughout the function. let let currentY: anycurrentY = y: anyy; // Each color is looked up by offset: palette[1 + offset] = the desired color. // C_RED_TEXT = 3, so offset = 3 - 1 = 2. That means palette[1 + 2] = palette[3] = red. // With BT.systemPrint() you would just write: BT.systemPrint(pos, C_RED_TEXT, text).
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.printFont: (font: BitmapFont, pos: Vector2i, text: string, paletteOffset?: number) => void
Draws text with a bitmap font through the indexed sprite pipeline. Supports proportional glyph widths and glyph-level offsets defined by the supplied {@link BitmapFont } . The font's underlying sprite sheet must have been indexized before calling this. Palette offset semantics and out-of-range behavior are identical to {@link BT.drawSprite } .
@since0.1.0@paramfont - Font asset used for rendering.@parampos - Text origin in display coordinates.@paramtext - String to render.@parampaletteOffset - Shift added to every stored glyph index before palette lookup (default 0).
printFont
(this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
, new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(10, let currentY: anycurrentY), 'Red Text', const C_RED_TEXT: 3C_RED_TEXT - 1);
let currentY: anycurrentY += lineHeight: anylineHeight;
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.printFont: (font: BitmapFont, pos: Vector2i, text: string, paletteOffset?: number) => void
Draws text with a bitmap font through the indexed sprite pipeline. Supports proportional glyph widths and glyph-level offsets defined by the supplied {@link BitmapFont } . The font's underlying sprite sheet must have been indexized before calling this. Palette offset semantics and out-of-range behavior are identical to {@link BT.drawSprite } .
@since0.1.0@paramfont - Font asset used for rendering.@parampos - Text origin in display coordinates.@paramtext - String to render.@parampaletteOffset - Shift added to every stored glyph index before palette lookup (default 0).
printFont
(this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
, new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(10, let currentY: anycurrentY), 'Green Text', const C_GREEN_TEXT: 4C_GREEN_TEXT - 1);
let currentY: anycurrentY += lineHeight: anylineHeight;
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.printFont: (font: BitmapFont, pos: Vector2i, text: string, paletteOffset?: number) => void
Draws text with a bitmap font through the indexed sprite pipeline. Supports proportional glyph widths and glyph-level offsets defined by the supplied {@link BitmapFont } . The font's underlying sprite sheet must have been indexized before calling this. Palette offset semantics and out-of-range behavior are identical to {@link BT.drawSprite } .
@since0.1.0@paramfont - Font asset used for rendering.@parampos - Text origin in display coordinates.@paramtext - String to render.@parampaletteOffset - Shift added to every stored glyph index before palette lookup (default 0).
printFont
(this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
, new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(10, let currentY: anycurrentY), 'Blue Text', const C_BLUE_TEXT: 5C_BLUE_TEXT - 1);
let currentY: anycurrentY += lineHeight: anylineHeight;
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.printFont: (font: BitmapFont, pos: Vector2i, text: string, paletteOffset?: number) => void
Draws text with a bitmap font through the indexed sprite pipeline. Supports proportional glyph widths and glyph-level offsets defined by the supplied {@link BitmapFont } . The font's underlying sprite sheet must have been indexized before calling this. Palette offset semantics and out-of-range behavior are identical to {@link BT.drawSprite } .
@since0.1.0@paramfont - Font asset used for rendering.@parampos - Text origin in display coordinates.@paramtext - String to render.@parampaletteOffset - Shift added to every stored glyph index before palette lookup (default 0).
printFont
(this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
, new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(10, let currentY: anycurrentY), 'Yellow Text', const C_YELLOW_TEXT: 6C_YELLOW_TEXT - 1);
// Add extra space after this section. let currentY: anycurrentY += lineHeight: anylineHeight + 4; return let currentY: anycurrentY; } // Draws text where each character has a different color, and the colors // shift over time to create a flowing rainbow animation. // The colors were pre-computed in update() and stored in palette slots C_RAINBOW_BASE+i. // This technique works with BT.printFont() because it draws one character at a time // with a different palette offset for each glyph. // y: the Y position to start drawing at. // lineHeight: how many pixels to move down between lines. // Returns the Y position after the text. Demo.renderRainbowText(y: any, lineHeight: any): anyrenderRainbowText(y: anyy, lineHeight: anylineHeight) { // Start drawing from the left margin (must match RAINBOW_ORIGIN_X used in update()). let let x: numberx = const RAINBOW_ORIGIN_X: 10RAINBOW_ORIGIN_X; let let slotIndex: numberslotIndex = 0; // Loop through each character in the string one at a time. for (const const char: anychar of const RAINBOW_TEXT: "Rainbow Animation!"RAINBOW_TEXT) { // The palette offset for character i = C_RAINBOW_BASE + i - 1. // This is because printFont offset N means palette[1 + N]. // We want palette[C_RAINBOW_BASE + i], so offset = C_RAINBOW_BASE + i - 1.
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.printFont: (font: BitmapFont, pos: Vector2i, text: string, paletteOffset?: number) => void
Draws text with a bitmap font through the indexed sprite pipeline. Supports proportional glyph widths and glyph-level offsets defined by the supplied {@link BitmapFont } . The font's underlying sprite sheet must have been indexized before calling this. Palette offset semantics and out-of-range behavior are identical to {@link BT.drawSprite } .
@since0.1.0@paramfont - Font asset used for rendering.@parampos - Text origin in display coordinates.@paramtext - String to render.@parampaletteOffset - Shift added to every stored glyph index before palette lookup (default 0).
printFont
(this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
, new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(let x: numberx, y: anyy), const char: anychar, const C_RAINBOW_BASE: 20C_RAINBOW_BASE - 1 + let slotIndex: numberslotIndex);
// Look up how wide this character is in the font's glyph table. // "advance" is the number of pixels to move right before drawing the next character. // This is unique to BitmapFont - each letter has its own width in a proportional font. // The built-in system font always advances systemCharWidth pixels per character (6 by default). const const glyph: Glyph | nullglyph = this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.getGlyph(char: string): Glyph | null
Returns glyph data for a character. Uses the ASCII lookup table for single-byte characters and falls back to the Unicode glyph map for everything else, then to the font's fallback glyph (see {@link FALLBACK_GLYPH_CHAR } ) when neither has an entry for the character.
@paramchar - Single character to look up (supports Unicode).@returnsGlyph metadata; the font's fallback glyph when the character is missing and a fallback is defined; otherwise `null`.
getGlyph
(const char: anychar);
// If the glyph exists, use its advance width; otherwise fall back to 7 pixels. let x: numberx += const glyph: Glyph | nullglyph ? const glyph: Glyphglyph.Glyph.advance: number
Horizontal advance after drawing (distance to next character).
advance
: 7;
let slotIndex: numberslotIndex++; } return y: anyy + lineHeight: anylineHeight + 4; } // Draws text that pulses in opacity - it fades in and out in a smooth rhythm (alpha pulsing). // The alpha value is pre-computed in update() using Math.sin and stored in palette slot C_PULSE. // This palette animation technique works exactly the same with BT.systemPrint(). // y: the Y position to start drawing at. // lineHeight: how many pixels to move down between lines. // Returns the Y position after the text. Demo.renderPulsingText(y: any, lineHeight: any): anyrenderPulsingText(y: anyy, lineHeight: anylineHeight) { // C_PULSE - 1 = 37. That means palette[1 + 37] = palette[38] = C_PULSE (the animated color).
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.printFont: (font: BitmapFont, pos: Vector2i, text: string, paletteOffset?: number) => void
Draws text with a bitmap font through the indexed sprite pipeline. Supports proportional glyph widths and glyph-level offsets defined by the supplied {@link BitmapFont } . The font's underlying sprite sheet must have been indexized before calling this. Palette offset semantics and out-of-range behavior are identical to {@link BT.drawSprite } .
@since0.1.0@paramfont - Font asset used for rendering.@parampos - Text origin in display coordinates.@paramtext - String to render.@parampaletteOffset - Shift added to every stored glyph index before palette lookup (default 0).
printFont
(this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
, new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(10, y: anyy), 'Pulsing Text', const C_PULSE: anyC_PULSE - 1);
return y: anyy + lineHeight: anylineHeight + 4; } // Shows that the font can draw special characters like multiplication signs. // y: the Y position to start drawing at. // lineHeight: how many pixels to move down between lines. // Returns the Y position after the text. Demo.renderSpecialCharacters(y: any, lineHeight: any): anyrenderSpecialCharacters(y: anyy, lineHeight: anylineHeight) { // Offset 0 = palette[1] = C_WHITE = white text. // The '\u00D7' is the Unicode multiplication sign (×), which is a non-ASCII character. // This tests that the font includes glyphs outside the basic Latin alphabet.
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.printFont: (font: BitmapFont, pos: Vector2i, text: string, paletteOffset?: number) => void
Draws text with a bitmap font through the indexed sprite pipeline. Supports proportional glyph widths and glyph-level offsets defined by the supplied {@link BitmapFont } . The font's underlying sprite sheet must have been indexized before calling this. Palette offset semantics and out-of-range behavior are identical to {@link BT.drawSprite } .
@since0.1.0@paramfont - Font asset used for rendering.@parampos - Text origin in display coordinates.@paramtext - String to render.@parampaletteOffset - Shift added to every stored glyph index before palette lookup (default 0).
printFont
(this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
, new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(10, y: anyy), 'Special: 3 \u00D7 4 = 12', 0);
return y: anyy + lineHeight: anylineHeight; } // Demonstrates font.measureText() - which tells you exactly how wide a string will // be before you draw it. We draw an underline that is exactly the right length. // BT.systemPrint() does not have a measureText() equivalent; this is a BitmapFont-only feature. // y: the Y position to start drawing at. // lineHeight: how many pixels to move down between lines. // Returns the Y position after the text and underline. Demo.renderTextMeasurement(y: any, lineHeight: any): anyrenderTextMeasurement(y: anyy, lineHeight: anylineHeight) { const const measureText: "Measured Width"measureText = 'Measured Width'; // Ask the font how many pixels wide this string will be when drawn. // The system font doesn't support this - it's a BitmapFont-specific feature. const const textWidth: numbertextWidth = this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.measureText(text: string): number
Measures the horizontal pixel width of a text string. Results are cached for repeated measurements. Iterates by Unicode code point (`for...of`), not by UTF-16 code unit, so an astral character (a surrogate pair) is measured as the single glyph it is instead of two lone-surrogate lookups. Glyph resolution (including the ASCII fast path and fallback-glyph substitution) goes through {@link getGlyph } , so a measured width always matches what actually renders.
@paramtext - String to measure.@returnsTotal width in pixels.
measureText
(const measureText: "Measured Width"measureText);
// Draw the text in light gray. // C_GRAY_TEXT - 1 = 6. That means palette[1 + 6] = palette[7] = C_GRAY_TEXT.
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.printFont: (font: BitmapFont, pos: Vector2i, text: string, paletteOffset?: number) => void
Draws text with a bitmap font through the indexed sprite pipeline. Supports proportional glyph widths and glyph-level offsets defined by the supplied {@link BitmapFont } . The font's underlying sprite sheet must have been indexized before calling this. Palette offset semantics and out-of-range behavior are identical to {@link BT.drawSprite } .
@since0.1.0@paramfont - Font asset used for rendering.@parampos - Text origin in display coordinates.@paramtext - String to render.@parampaletteOffset - Shift added to every stored glyph index before palette lookup (default 0).
printFont
(this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
, new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(10, y: anyy), const measureText: "Measured Width"measureText, const C_GRAY_TEXT: 7C_GRAY_TEXT - 1);
// Draw an orange underline that is exactly as wide as the text we measured. // The underline sits 2 pixels above the bottom of the line. // BT.drawLine() takes start point, end point, and a palette slot number (not an offset).
const BT: {
    FLIP_H: number;
    FLIP_V: number;
    ROT_90_CW: number;
    ROT_180_CW: number;
    ROT_270_CW: number;
    BTN_UP: number;
    BTN_DOWN: number;
    BTN_LEFT: number;
    BTN_RIGHT: number;
    BTN_A: number;
    BTN_B: number;
    BTN_X: number;
    BTN_Y: number;
    BTN_L: number;
    BTN_R: number;
    BTN_START: number;
    BTN_SELECT: number;
    BTN_POINTER_A: number;
    BTN_POINTER_B: number;
    BTN_POINTER_C: number;
    BTN_POINTER_D: number;
    PLAYER_ONE: number;
    PLAYER_TWO: number;
    PLAYER_THREE: number;
    PLAYER_FOUR: number;
    AXIS_LEFT_X: number;
    AXIS_LEFT_Y: number;
    AXIS_RIGHT_X: number;
    AXIS_RIGHT_Y: number;
    AXIS_TRIGGER_L: number;
    ... 106 more ...;
    spritesRefresh: () => void;
}
Main BLIT386 API namespace used by runtime demos.
BT
.drawLine: (p0: Vector2i, p1: Vector2i, paletteIndex: number) => void
Draws a pixel-perfect line between two points. Uses rasterized line drawing without antialiasing.
@since0.1.0@paramp0 - Start position in display coordinates.@paramp1 - End position in display coordinates.@parampaletteIndex - Palette color index.
drawLine
(
new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(10, y: anyy + lineHeight: anylineHeight - 2),
new new Vector2i(x?: number, y?: number): Vector2i
Creates an integer 2D vector, truncating inputs toward zero.
@paramx - Horizontal component (defaults to 0).@paramy - Vertical component (defaults to 0).
Vector2i
(10 + const textWidth: numbertextWidth, y: anyy + lineHeight: anylineHeight - 2),
const C_ORANGE_LINE: 8C_ORANGE_LINE, ); return y: anyy + lineHeight: anylineHeight + 4; } // Draws a small panel of BitmapFont metadata: the font's name, point size, and how many // glyphs (letter pictures) it contains. This is demo-specific info that only BitmapFont // exposes; the built-in system font has no name or glyph count you can print this way. // The panel is drawn with the shared UI kit: everything between ui.begin() and ui.end() // stacks into one bordered group that the kit sizes and anchors for us. Demo.renderFontInfo(): voidrenderFontInfo() { // Anchor the group to the bottom-right corner of the screen, away from the showcase // text on the left and the engine overlay's toggle hint in the bottom-left corner. import uiui.begin(import UI_ANCHORSUI_ANCHORS.BOTTOM_RIGHT); // Give the group a background, border, and an amber title. import uiui.panel('Font Info'); // ui.kv() draws an aligned "KEY: value" row - the key dim, the value bright. import uiui.kv('FONT', this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.name: string
Font display name.
name
);
import uiui.kv('SIZE', `${this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.size: number
Original font size in points.
size
}pt`);
import uiui.kv('GLYPHS', this.Demo.font: BitmapFont | null
@type{BitmapFont | null}
font
.BitmapFont.glyphCount: number
Returns the total number of glyphs loaded into the font.
@returnsTotal glyph count.
glyphCount
);
// end() closes the group: the kit measures the rows, places the panel, and draws it. import uiui.end(); } } // Hand the Demo class to BLIT386 to start the demo loop. function bootstrap(DemoClass: DemoConstructor, options?: BootstrapOptions): Promise<boolean>
One-liner bootstrap function for BLIT386 demos. Handles canvas retrieval and engine initialization. Backend selection (WebGPU or software fallback) is managed internally by BTAPI. This function provides a streamlined way to start a demo with sensible defaults while allowing customization through options.
@since0.2.0@changed1.4.0 Calling `bootstrap()` again while already initialized now routes to a hot swap (via {@link registerHotReload}) when a Vite HMR context is registered, or logs a double-bootstrap guard and returns `false` otherwise - previously it silently started a second, unstoppable `GameLoop`.@changed1.7.0 Exposes `BT` on `window.BT` after bootstrap finishes, gated by {@link BootstrapOptions.exposeGlobal} (default: {@link BT.isDevMode}).@paramDemoClass - Demo class constructor implementing `IBTDemo` (optional `configure()` for hardware settings).@paramoptions - Optional configuration for IDs and callbacks.@returns`true` when the demo boots successfully; otherwise `false`.@example// Simplest usage - uses default IDs. bootstrap(MyDemo);@example// With custom options. bootstrap(MyDemo, { canvasID: 'custom-canvas', containerID: 'custom-container', onSuccess: () => console.log('Demo started!'), onError: (err) => analytics.trackError(err), });@example// Await the result. const success = await bootstrap(MyDemo); if (success) { console.log('Demo is running'); }
bootstrap
(class Demo
Demonstrates bitmap font loading and rendering with various text effects. Shows static colors, animated rainbow effects, text measurement, and font metadata. Contrast this approach with BT.systemPrint() used in the Fonts demo.
@implementsIBTDemo
Demo
);