// Random Basics: the shuffling, weighting, and scattering tools built into the engine.
// @description Five scenes for the BT.random generators: shuffling, weighted drops, scatter, flips, and walkers.
//
// Part of the BLIT386 demo series.
//
// Prerequisites:
//   Basics     https://demos.blit386.dev/basics
//   Primitives https://demos.blit386.dev/primitives
//   Colors     https://demos.blit386.dev/colors
//
// WHAT YOU WILL SEE
// Five small scenes, one at a time. Press 1-5 (or tap the buttons) to switch between them.
// Each scene shows off one way of asking the engine for a random result:
//   1. Shuffle    - mixing a row of cards, and the difference between the two ways to do it
//   2. Weighted   - a treasure chest where rare prizes really are rare
//   3. Gaussian   - arrows landing near a target instead of anywhere at all
//   4. Sign       - a coin flip that answers "left" or "right"
//   5. Directions - two bugs walking a grid, one allowed 4 ways, the other allowed 8
//
// WHAT YOU WILL LEARN
//   - BT.random.shuffle() hands back a NEW mixed-up copy and leaves your list alone
//   - BT.random.shuffleInPlace() mixes up the list you gave it, so the old order is gone
//   - BT.random.weighted() lets you say "this prize should show up 70 times as often"
//   - BT.random.gaussian() clumps results near a middle value instead of spreading them evenly
//   - BT.random.sign() answers -1 or 1, which is perfect for "which way?" questions
//   - BT.random.direction4() and direction8() hand back a ready-made step as a Vector2i
//
// A NOTE ON WHAT IS NOT HERE
// The everyday tools - int(), float(), and pick() - already appear all over the other demos,
// so this one covers the ones you have not met yet. The Camera demo uses int() and
// pointInRange() to scatter buildings: https://demos.blit386.dev/camera
//
// The engine splits work the usual way: update() moves things; render() only draws.
// See the Basics demo for the full story: https://demos.blit386.dev/basics

import { 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 Rect2i
Integer rectangle for pixel-perfect bounds and regions. Used throughout the engine for sprite regions, display-space bounds, and zero-allocation geometry helpers. Both convenience getters and allocation-free `*To()` helpers are provided so callers can choose between readability and hot-path efficiency.
@since0.1.0
Rect2i
, 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';
import { import applyThemeapplyTheme, import uiui, import UI_ANCHORSUI_ANCHORS } from './shared/ui.js'; /** @typedef {import('blit386').IBTDemo} IBTDemo */ /** @typedef {import('blit386').Palette} Palette */ // This demo runs at the engine's default screen size of 320x240 "game pixels", which is what // every position and size below is measured in. // The five scenes, in the order the number keys select them. const const MODE_SHUFFLE: 0MODE_SHUFFLE = 0; const const MODE_WEIGHTED: 1MODE_WEIGHTED = 1; const const MODE_GAUSSIAN: 2MODE_GAUSSIAN = 2; const const MODE_SIGN: 3MODE_SIGN = 3; const const MODE_DIRECTIONS: 4MODE_DIRECTIONS = 4; // Names shown in the mode panel. The array position matches the MODE_* numbers above. const const MODE_NAMES: {}MODE_NAMES = ['Shuffle', 'Weighted', 'Gaussian', 'Sign', 'Directions']; // Color slots. The shared UI kit owns slots 240-251, so scene colors stay well below that. const const C_BG: 1C_BG = 1; // Dark background behind every scene. const const C_INK: 2C_INK = 2; // Bright text and outlines. const const C_DIM: 3C_DIM = 3; // Faded lines: guides, grids, and old trails. const const C_TARGET: 4C_TARGET = 4; // The target rings in the Gaussian scene. const const C_SHOT: 5C_SHOT = 5; // Arrows that used gaussian(). const const C_SHOT_FLAT: 6C_SHOT_FLAT = 6; // Arrows that used float() instead, for comparison. const const C_BUG_A: 7C_BUG_A = 7; // The 4-direction bug. const const C_BUG_B: 8C_BUG_B = 8; // The 8-direction bug. // The eight cards in the shuffle scene each get their own color, in slots 10-17. const const C_CARD_BASE: 10C_CARD_BASE = 10; const const CARD_COUNT: 8CARD_COUNT = 8; // Card size, and how far apart their left edges sit. Eight cards at 34 pixels apart, starting // 22 pixels in, reach x = 294 - just inside the 320-pixel screen. const const CARD_W: 26CARD_W = 26; const const CARD_H: 34CARD_H = 34; const const CARD_STRIDE: 34CARD_STRIDE = 34; const const CARD_LEFT: 22CARD_LEFT = 22; // The four treasure tiers each get their own color, in slots 20-23. const const C_TIER_BASE: 20C_TIER_BASE = 20; // Treasure tiers, rarest last. `TIER_INDEXES` is what we actually hand to weighted(): // asking for the index rather than the name means the answer can be used to look up both // the label and the color without searching the array afterward. const const TIER_NAMES: {}TIER_NAMES = ['Common', 'Uncommon', 'Rare', 'Legendary']; const const TIER_INDEXES: {}TIER_INDEXES = [0, 1, 2, 3]; const const TIER_WEIGHTS: {}TIER_WEIGHTS = [70, 20, 9, 1]; // How many update ticks pass between automatic treasure drops. const const DROP_EVERY_TICKS: 8DROP_EVERY_TICKS = 8; // The falling gems disappear once they reach this line. const const DROP_FLOOR_Y: 132DROP_FLOOR_Y = 132; // How many arrows stay on screen in the Gaussian scene before the oldest is reused. const const SHOT_COUNT: 120SHOT_COUNT = 120; // How many update ticks pass between arrows. const const SHOT_EVERY_TICKS: 3SHOT_EVERY_TICKS = 3; // Where the target sits, and how wide its rings are. const const TARGET_CENTER: Vector2iTARGET_CENTER = 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
(160, 76);
const const TARGET_RINGS: {}TARGET_RINGS = [44, 33, 22, 11]; // The Sign scene walks a dot along this line. const const WALK_Y: 88WALK_Y = 88; const const WALK_LEFT: 40WALK_LEFT = 40; const const WALK_RIGHT: 280WALK_RIGHT = 280; // How many update ticks pass between walker steps and bug steps. const const STEP_EVERY_TICKS: 6STEP_EVERY_TICKS = 6; // The Directions scene gives each bug its own square to wander, and remembers this many // of its recent positions as a trail. const const BUG_AREA_A: Rect2iBUG_AREA_A = new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(24, 28, 120, 94);
const const BUG_AREA_B: Rect2iBUG_AREA_B = new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(176, 28, 120, 94);
const const TRAIL_LENGTH: 90TRAIL_LENGTH = 90; // Each bug is drawn as a small square centered on its position, reaching BUG_REACH pixels // out in every direction. The bug therefore has to stop BUG_REACH short of its square's // edge, or half the marker would hang outside the frame. const const BUG_REACH: 2BUG_REACH = 2; const const BUG_SIZE: numberBUG_SIZE = const BUG_REACH: 2BUG_REACH * 2 + 1; /** * Clamps a whole number so it never leaves the range min..max. * * "Clamp" means "keep it inside the fence": if the value wandered past either end, this * pushes it back to the nearest edge. * * @param {number} value * @param {number} min * @param {number} max * @returns {number} */ function function clampInt(value: number, min: number, max: number): number
Clamps a whole number so it never leaves the range min..max. "Clamp" means "keep it inside the fence": if the value wandered past either end, this pushes it back to the nearest edge.
@paramvalue@parammin@parammax@returns
clampInt
(value: number
@paramvalue
value
, min: number
@parammin
min
, max: number
@parammax
max
) {
if (value: number
@paramvalue
value
< min: number
@parammin
min
) {
return min: number
@parammin
min
;
} if (value: number
@paramvalue
value
> max: number
@parammax
max
) {
return max: number
@parammax
max
;
} return value: number
@paramvalue
value
;
} /** * Five small scenes covering the parts of BT.random the other demos do not use. * * @implements {IBTDemo} */ class class Demo
Five small scenes covering the parts of BT.random the other demos do not use.
@implementsIBTDemo
Demo
{
/** @type {Palette | null} */ Demo.palette: Palette | null
@type{Palette | null}
palette
= null;
// Slot map for the shared UI kit theme, filled in by applyTheme() during init(). Demo.theme: nulltheme = null; // Which scene is on screen right now. Starts on the shuffle cards. Demo.mode: numbermode = const MODE_SHUFFLE: 0MODE_SHUFFLE; // Counts update ticks so the scenes can act every few ticks instead of every single one. Demo.ticks: numberticks = 0; // SHUFFLE SCENE // `deck` is the real list of cards. `shuffled` is the copy that shuffle() handed back. // Keeping them apart is the whole point of this scene: one button changes only the copy, // the other button changes the list itself. Demo.deck: {}deck = []; Demo.shuffled: {}shuffled = []; // WEIGHTED SCENE // How many of each tier have dropped so far, and the gems currently falling. Demo.tierCounts: {}tierCounts = [0, 0, 0, 0]; Demo.gems: {}gems = []; // GAUSSIAN SCENE // A fixed-size ring of arrow positions. `shotNext` says which slot the next arrow // overwrites, so the oldest arrow quietly disappears without any array shuffling. Demo.shots: {}shots = []; Demo.shotNext: numbershotNext = 0; Demo.shotSpread: numbershotSpread = 18; Demo.useGaussian: booleanuseGaussian = true; // SIGN SCENE // Where the walker stands, and how many times each answer has come up. Demo.walkX: numberwalkX = (const WALK_LEFT: 40WALK_LEFT + const WALK_RIGHT: 280WALK_RIGHT) / 2; Demo.leftCount: numberleftCount = 0; Demo.rightCount: numberrightCount = 0; // DIRECTIONS SCENE // Each bug remembers where it is and where it has been.
Demo.bugA: {
    pos: Vector2i;
    trail: {};
}
bugA
= { pos: Vector2ipos: 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
(0, 0), trail: {}trail: [] };
Demo.bugB: {
    pos: Vector2i;
    trail: {};
}
bugB
= { pos: Vector2ipos: 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
(0, 0), trail: {}trail: [] };
/** * Builds the palette and fills in the starting state of every scene. * * @returns {Promise<boolean>} */ async Demo.init(): Promise<boolean>
Builds the palette and fills in the starting state of every scene.
@returns
init
() {
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);
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_BG: 1C_BG, 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
(14, 16, 26)); // Near-black blue background.
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_INK: 2C_INK, 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
(226, 232, 244)); // Bright text and outlines.
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_DIM: 3C_DIM, 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
(72, 80, 102)); // Faded guides and grids.
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_TARGET: 4C_TARGET, 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
(196, 148, 64)); // Amber target rings.
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_SHOT: 5C_SHOT, 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
(120, 226, 168)); // Green arrows: gaussian().
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_SHOT_FLAT: 6C_SHOT_FLAT, 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
(226, 120, 140)); // Red arrows: float().
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_BUG_A: 7C_BUG_A, 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
(126, 190, 255)); // Blue 4-direction bug.
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_BUG_B: 8C_BUG_B, 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, 186, 110)); // Orange 8-direction bug.
// Eight card colors spread around the rainbow, so a reordering is obvious at a glance. // A "hue" is a position on the color wheel: 0 is red, 120 is green, 240 is blue, and // 360 comes back around to red. Stepping evenly around the wheel is the quickest way // to get eight colors nobody could confuse with each other. for (let let i: numberi = 0; let i: numberi < const CARD_COUNT: 8CARD_COUNT; let i: numberi++) { const const hue: numberhue = (let i: numberi / const CARD_COUNT: 8CARD_COUNT) * 360; // fromHSL takes the hue, then how colorful it is (0-100), then how light (0-100). 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_CARD_BASE: 10C_CARD_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, 70, 62));
} // Four treasure colors, getting brighter as the prize gets rarer. 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_TIER_BASE: 20C_TIER_BASE + 0, 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
(140, 150, 165)); // Common: dull 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_TIER_BASE: 20C_TIER_BASE + 1, 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
(120, 210, 140)); // Uncommon: 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_TIER_BASE: 20C_TIER_BASE + 2, 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
(120, 170, 255)); // Rare: 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_TIER_BASE: 20C_TIER_BASE + 3, 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, 210, 110)); // Legendary: gold.
// Install the shared UI colors, then hand the finished palette to the engine. // applyTheme() must come before paletteSet() so the kit's colors are included. this.Demo.theme: nulltheme = import applyThemeapplyTheme(this.Demo.palette: Palette
@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
.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
);
// The deck starts in order: card 0, card 1, card 2, and so on. Starting tidy means // the first shuffle is easy to see. for (let let i: numberi = 0; let i: numberi < const CARD_COUNT: 8CARD_COUNT; let i: numberi++) { this.Demo.deck: {}deck.push(let i: numberi); } // Before anyone presses a button, the "shuffled copy" is just a copy of the deck. this.Demo.shuffled: {}shuffled = this.Demo.deck: {}deck.slice(); // Fill the arrow ring with off-screen positions so nothing is drawn until the first // arrow is actually fired. for (let let i: numberi = 0; let i: numberi < const SHOT_COUNT: 120SHOT_COUNT; let i: numberi++) { this.Demo.shots: {}shots.push({ x: numberx: -100, y: numbery: -100, wasGaussian: booleanwasGaussian: true }); } // Start each bug in the middle of its own square. this.
Demo.bugA: {
    pos: Vector2i;
    trail: {};
}
bugA
.pos: Vector2ipos = 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 BUG_AREA_A: Rect2iBUG_AREA_A.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
+ Math.floor(const BUG_AREA_A: Rect2iBUG_AREA_A.Rect2i.width: number
Width in pixels (defaults to 0).
width
/ 2),
const BUG_AREA_A: Rect2iBUG_AREA_A.Rect2i.y: number
Top edge Y coordinate (defaults to 0).
y
+ Math.floor(const BUG_AREA_A: Rect2iBUG_AREA_A.Rect2i.height: number
Height in pixels (defaults to 0).
height
/ 2),
); this.
Demo.bugB: {
    pos: Vector2i;
    trail: {};
}
bugB
.pos: Vector2ipos = 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 BUG_AREA_B: Rect2iBUG_AREA_B.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
+ Math.floor(const BUG_AREA_B: Rect2iBUG_AREA_B.Rect2i.width: number
Width in pixels (defaults to 0).
width
/ 2),
const BUG_AREA_B: Rect2iBUG_AREA_B.Rect2i.y: number
Top edge Y coordinate (defaults to 0).
y
+ Math.floor(const BUG_AREA_B: Rect2iBUG_AREA_B.Rect2i.height: number
Height in pixels (defaults to 0).
height
/ 2),
); return true; } /** * Advances whichever scene is currently on screen. */ Demo.update(): void
Advances whichever scene is currently on screen.
update
() {
// Always first: this is what makes the { key } shortcuts on buttons work. import uiui.tick(); this.Demo.ticks: numberticks++; // Number keys jump straight to a scene. Reading key presses here in update() - never // in render() - is what keeps a quick tap from being missed. if (
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
.isKeyPressed: (key: string, repeatRate?: number) => boolean
Checks whether a keyboard key was pressed on the current fixed-update tick. Optional `repeatRate` is in fixed ticks between repeats (`0` or omitted = edge only). When `repeatRate > 0`, repeats fire while held per `(ticks - firstPressTick) > 0 && (ticks - firstPressTick) % repeatRate === 0`. Call from `update()`, not `render()`: the press edge clears once per fixed-update tick, which always runs before that frame's `render()`, so a press read from `render()` can be intermittently missed under rapid input.
@since1.1.1@paramkey - DOM keyboard code string.@paramrepeatRate - Ticks between repeat triggers; omit or `0` for no repeat.@returns`true` on the press edge (and on repeat ticks when configured).
isKeyPressed
('Digit1')) {
this.Demo.mode: numbermode = const MODE_SHUFFLE: 0MODE_SHUFFLE; } if (
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
.isKeyPressed: (key: string, repeatRate?: number) => boolean
Checks whether a keyboard key was pressed on the current fixed-update tick. Optional `repeatRate` is in fixed ticks between repeats (`0` or omitted = edge only). When `repeatRate > 0`, repeats fire while held per `(ticks - firstPressTick) > 0 && (ticks - firstPressTick) % repeatRate === 0`. Call from `update()`, not `render()`: the press edge clears once per fixed-update tick, which always runs before that frame's `render()`, so a press read from `render()` can be intermittently missed under rapid input.
@since1.1.1@paramkey - DOM keyboard code string.@paramrepeatRate - Ticks between repeat triggers; omit or `0` for no repeat.@returns`true` on the press edge (and on repeat ticks when configured).
isKeyPressed
('Digit2')) {
this.Demo.mode: numbermode = const MODE_WEIGHTED: 1MODE_WEIGHTED; } if (
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
.isKeyPressed: (key: string, repeatRate?: number) => boolean
Checks whether a keyboard key was pressed on the current fixed-update tick. Optional `repeatRate` is in fixed ticks between repeats (`0` or omitted = edge only). When `repeatRate > 0`, repeats fire while held per `(ticks - firstPressTick) > 0 && (ticks - firstPressTick) % repeatRate === 0`. Call from `update()`, not `render()`: the press edge clears once per fixed-update tick, which always runs before that frame's `render()`, so a press read from `render()` can be intermittently missed under rapid input.
@since1.1.1@paramkey - DOM keyboard code string.@paramrepeatRate - Ticks between repeat triggers; omit or `0` for no repeat.@returns`true` on the press edge (and on repeat ticks when configured).
isKeyPressed
('Digit3')) {
this.Demo.mode: numbermode = const MODE_GAUSSIAN: 2MODE_GAUSSIAN; } if (
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
.isKeyPressed: (key: string, repeatRate?: number) => boolean
Checks whether a keyboard key was pressed on the current fixed-update tick. Optional `repeatRate` is in fixed ticks between repeats (`0` or omitted = edge only). When `repeatRate > 0`, repeats fire while held per `(ticks - firstPressTick) > 0 && (ticks - firstPressTick) % repeatRate === 0`. Call from `update()`, not `render()`: the press edge clears once per fixed-update tick, which always runs before that frame's `render()`, so a press read from `render()` can be intermittently missed under rapid input.
@since1.1.1@paramkey - DOM keyboard code string.@paramrepeatRate - Ticks between repeat triggers; omit or `0` for no repeat.@returns`true` on the press edge (and on repeat ticks when configured).
isKeyPressed
('Digit4')) {
this.Demo.mode: numbermode = const MODE_SIGN: 3MODE_SIGN; } if (
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
.isKeyPressed: (key: string, repeatRate?: number) => boolean
Checks whether a keyboard key was pressed on the current fixed-update tick. Optional `repeatRate` is in fixed ticks between repeats (`0` or omitted = edge only). When `repeatRate > 0`, repeats fire while held per `(ticks - firstPressTick) > 0 && (ticks - firstPressTick) % repeatRate === 0`. Call from `update()`, not `render()`: the press edge clears once per fixed-update tick, which always runs before that frame's `render()`, so a press read from `render()` can be intermittently missed under rapid input.
@since1.1.1@paramkey - DOM keyboard code string.@paramrepeatRate - Ticks between repeat triggers; omit or `0` for no repeat.@returns`true` on the press edge (and on repeat ticks when configured).
isKeyPressed
('Digit5')) {
this.Demo.mode: numbermode = const MODE_DIRECTIONS: 4MODE_DIRECTIONS; } // Only the scene being looked at needs to do any work. if (this.Demo.mode: numbermode === const MODE_WEIGHTED: 1MODE_WEIGHTED) { this.Demo.updateWeighted(): void
Drops a new gem every few ticks and moves the falling ones down the screen.
updateWeighted
();
} else if (this.Demo.mode: numbermode === const MODE_GAUSSIAN: 2MODE_GAUSSIAN) { this.Demo.updateGaussian(): void
Fires an arrow at the target every few ticks.
updateGaussian
();
} else if (this.Demo.mode: numbermode === const MODE_SIGN: 3MODE_SIGN) { this.Demo.updateSign(): void
Steps the walker left or right.
updateSign
();
} else if (this.Demo.mode: numbermode === const MODE_DIRECTIONS: 4MODE_DIRECTIONS) { this.Demo.updateDirections(): void
Steps both bugs and records where they have been.
updateDirections
();
} } /** * Draws the current scene, then the panels on top of it. */ Demo.render(): void
Draws the current scene, then the panels on top of it.
render
() {
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
(const C_BG: 1C_BG);
if (this.Demo.mode: numbermode === const MODE_SHUFFLE: 0MODE_SHUFFLE) { this.Demo.renderShuffle(): void
Draws the two rows of cards.
renderShuffle
();
} else if (this.Demo.mode: numbermode === const MODE_WEIGHTED: 1MODE_WEIGHTED) { this.Demo.renderWeighted(): void
Draws the chest, the falling gems, and the tier tally.
renderWeighted
();
} else if (this.Demo.mode: numbermode === const MODE_GAUSSIAN: 2MODE_GAUSSIAN) { this.Demo.renderGaussian(): void
Draws the target and every arrow currently stuck in it.
renderGaussian
();
} else if (this.Demo.mode: numbermode === const MODE_SIGN: 3MODE_SIGN) { this.Demo.renderSign(): void
Draws the walking line and the dot standing on it.
renderSign
();
} else { this.Demo.renderDirections(): void
Draws both bugs and their trails.
renderDirections
();
} // The mode picker sits in the same corner in every scene, so it never moves around. // Two arrow buttons rather than five named ones: at 320x240 a five-row panel would // swallow half the screen, and the number keys still jump straight to a scene. import uiui.begin(import UI_ANCHORSUI_ANCHORS.BOTTOM_LEFT); import uiui.panel(`Scene ${this.Demo.mode: numbermode + 1}/5 (keys 1-5)`); import uiui.label(const MODE_NAMES: {}MODE_NAMES[this.Demo.mode: numbermode], { color: stringcolor: 'accent' }); // The two buttons are tappable, so someone on a phone can reach every scene without // a keyboard. Adding MODE_NAMES.length before taking the remainder keeps the answer // positive when stepping back from scene 1. if (import uiui.button('< Prev')) { this.Demo.mode: numbermode = (this.Demo.mode: numbermode + const MODE_NAMES: {}MODE_NAMES.length - 1) % const MODE_NAMES: {}MODE_NAMES.length; } if (import uiui.button('Next >')) { this.Demo.mode: numbermode = (this.Demo.mode: numbermode + 1) % const MODE_NAMES: {}MODE_NAMES.length; } import uiui.end(); // Each scene adds its own controls and readouts in the opposite corner. if (this.Demo.mode: numbermode === const MODE_SHUFFLE: 0MODE_SHUFFLE) { this.Demo.renderShufflePanel(): void
The two shuffle buttons, which are the whole lesson of this scene.
renderShufflePanel
();
} else if (this.Demo.mode: numbermode === const MODE_WEIGHTED: 1MODE_WEIGHTED) { this.Demo.renderWeightedPanel(): void
The running tally of how often each tier has dropped.
renderWeightedPanel
();
} else if (this.Demo.mode: numbermode === const MODE_GAUSSIAN: 2MODE_GAUSSIAN) { this.Demo.renderGaussianPanel(): void
The spread slider and the flat-versus-clumped switch.
renderGaussianPanel
();
} else if (this.Demo.mode: numbermode === const MODE_SIGN: 3MODE_SIGN) { this.Demo.renderSignPanel(): void
How many times sign() answered each way.
renderSignPanel
();
} else { this.Demo.renderDirectionsPanel(): void
A reminder of what separates the two bugs.
renderDirectionsPanel
();
} } /** * Drops a new gem every few ticks and moves the falling ones down the screen. */ Demo.updateWeighted(): void
Drops a new gem every few ticks and moves the falling ones down the screen.
updateWeighted
() {
if (this.Demo.ticks: numberticks % const DROP_EVERY_TICKS: 8DROP_EVERY_TICKS === 0) { this.Demo.dropGem(): void
Asks weighted() for one treasure tier and starts a gem falling.
dropGem
();
} // Walk the list backward so removing an item cannot make the loop skip the next one. for (let let i: numberi = this.Demo.gems: {}gems.length - 1; let i: numberi >= 0; let i: numberi--) { const const gem: anygem = this.Demo.gems: {}gems[let i: numberi]; const gem: anygem.y += 2; if (const gem: anygem.y >= const DROP_FLOOR_Y: 132DROP_FLOOR_Y) { this.Demo.gems: {}gems.splice(let i: numberi, 1); } } } /** * Asks weighted() for one treasure tier and starts a gem falling. */ Demo.dropGem(): void
Asks weighted() for one treasure tier and starts a gem falling.
dropGem
() {
// weighted() picks one entry from the first list, using the second list as the // "how often should this win?" numbers. The weights here are 70, 20, 9, and 1, so // Common turns up roughly 70 times for every 1 Legendary. // // We hand it TIER_INDEXES (0, 1, 2, 3) rather than the names, because the number it // returns is then ready to use as a position in TIER_NAMES and as a color slot. const const tier: anytier =
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.weighted<any>(items: readonly any[], weights: readonly number[]): any
Returns one item chosen by relative weights.
@paramitems - Items to choose from.@paramweights - Non-negative weights parallel to `items`; total must be greater than 0.@returnsChosen item.@since1.5.0
weighted
(const TIER_INDEXES: {}TIER_INDEXES, const TIER_WEIGHTS: {}TIER_WEIGHTS);
this.Demo.tierCounts: {}tierCounts[const tier: anytier]++; this.Demo.gems: {}gems.push({ // int(a, b) gives a whole number from a up to (but not including) b, so this lands // somewhere across the middle of the screen. x: numberx:
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.int(minOrMaxExclusive: number, maxExclusive?: number): number
Returns a pseudo-random integer in [0, maxExclusive) or [min, maxExclusive).
@paramminOrMaxExclusive - When alone, exclusive upper bound from 0; otherwise inclusive min.@parammaxExclusive - Exclusive upper bound when two arguments are passed.@returnsWhole number in the half-open range.@since1.5.0
int
(110, 210),
y: numbery: 40, tier: anytier, }); } /** * Fires an arrow at the target every few ticks. */ Demo.updateGaussian(): void
Fires an arrow at the target every few ticks.
updateGaussian
() {
if (this.Demo.ticks: numberticks % const SHOT_EVERY_TICKS: 3SHOT_EVERY_TICKS !== 0) { return; } const const shot: anyshot = this.Demo.shots: {}shots[this.Demo.shotNext: numbershotNext]; if (this.Demo.useGaussian: booleanuseGaussian) { // gaussian(middle, spread) clumps its answers around the middle value. Most land // close to it, a few land further out, and the really wild ones are rare - the // same way most people are close to average height and giants are unusual. const shot: anyshot.x = const TARGET_CENTER: Vector2iTARGET_CENTER.Vector2i.x: number
Horizontal component (defaults to 0).
x
+ Math.round(
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.gaussian(mean?: number, stddev?: number): number
Returns a sample from an approximate normal distribution (Box-Muller, no spare).
@parammean - Distribution mean; defaults to 0.@paramstddev - Standard deviation; defaults to 1.@returnsGaussian sample.@since1.5.0
gaussian
(0, this.Demo.shotSpread: numbershotSpread));
const shot: anyshot.y = const TARGET_CENTER: Vector2iTARGET_CENTER.Vector2i.y: number
Vertical component (defaults to 0).
y
+ Math.round(
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.gaussian(mean?: number, stddev?: number): number
Returns a sample from an approximate normal distribution (Box-Muller, no spare).
@parammean - Distribution mean; defaults to 0.@paramstddev - Standard deviation; defaults to 1.@returnsGaussian sample.@since1.5.0
gaussian
(0, this.Demo.shotSpread: numbershotSpread));
} else { // float(a, b) is the flat version: every distance from the middle is equally // likely, so the arrows spread out into an even square with no clump at all. const const reach: numberreach = this.Demo.shotSpread: numbershotSpread * 2; const shot: anyshot.x = const TARGET_CENTER: Vector2iTARGET_CENTER.Vector2i.x: number
Horizontal component (defaults to 0).
x
+ Math.round(
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.float(min: number, max: number): number
Returns the next pseudo-random float in [min, max).
@parammin - Inclusive lower bound.@parammax - Exclusive upper bound.@returnsFloat in [min, max).@since1.5.0
float
(-const reach: numberreach, const reach: numberreach));
const shot: anyshot.y = const TARGET_CENTER: Vector2iTARGET_CENTER.Vector2i.y: number
Vertical component (defaults to 0).
y
+ Math.round(
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.float(min: number, max: number): number
Returns the next pseudo-random float in [min, max).
@parammin - Inclusive lower bound.@parammax - Exclusive upper bound.@returnsFloat in [min, max).@since1.5.0
float
(-const reach: numberreach, const reach: numberreach));
} const shot: anyshot.wasGaussian = this.Demo.useGaussian: booleanuseGaussian; // Move to the next slot, wrapping back to 0 at the end. This is why the oldest arrow // vanishes without any list being rebuilt. this.Demo.shotNext: numbershotNext = (this.Demo.shotNext: numbershotNext + 1) % const SHOT_COUNT: 120SHOT_COUNT; } /** * Steps the walker left or right. */ Demo.updateSign(): void
Steps the walker left or right.
updateSign
() {
if (this.Demo.ticks: numberticks % const STEP_EVERY_TICKS: 6STEP_EVERY_TICKS !== 0) { return; } // sign() answers -1 or 1, nothing else. Multiplying a distance by it turns "how far" // into "how far, and which way" in a single step. const const direction: 1 | -1direction =
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.sign(): -1 | 1
Returns -1 or 1 with equal probability.
@returnsEither `-1` or `1`.@since1.5.0
sign
();
if (const direction: 1 | -1direction < 0) { this.Demo.leftCount: numberleftCount++; } else { this.Demo.rightCount: numberrightCount++; } this.Demo.walkX: numberwalkX = function clampInt(value: number, min: number, max: number): number
Clamps a whole number so it never leaves the range min..max. "Clamp" means "keep it inside the fence": if the value wandered past either end, this pushes it back to the nearest edge.
@paramvalue@parammin@parammax@returns
clampInt
(this.Demo.walkX: numberwalkX + const direction: 1 | -1direction * 6, const WALK_LEFT: 40WALK_LEFT, const WALK_RIGHT: 280WALK_RIGHT);
} /** * Steps both bugs and records where they have been. */ Demo.updateDirections(): void
Steps both bugs and records where they have been.
updateDirections
() {
if (this.Demo.ticks: numberticks % const STEP_EVERY_TICKS: 6STEP_EVERY_TICKS !== 0) { return; } // direction4() hands back a Vector2i that is one step up, down, left, or right - the // four ways a rook moves in chess. No diagonals. this.
Demo.stepBug(bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}, step: Vector2i, area: Rect2i): void
Moves one bug by one step and remembers the position it left behind.
@parambug@paramstep - One step, from direction4() or direction8().@paramarea - The square this bug is allowed to wander inside.
stepBug
(this.
Demo.bugA: {
    pos: Vector2i;
    trail: {};
}
bugA
,
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.direction4(): Vector2i
Returns one of the four cardinal unit directions (Y-down). Possible values: `(1, 0)`, `(-1, 0)`, `(0, 1)`, `(0, -1)`.
@returnsNew unit vector.@since1.5.0
direction4
(), const BUG_AREA_A: Rect2iBUG_AREA_A);
// direction8() adds the four diagonals, so this bug has eight choices - the way a king // moves in chess. Its trail ends up looking rounder and less blocky. this.
Demo.stepBug(bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}, step: Vector2i, area: Rect2i): void
Moves one bug by one step and remembers the position it left behind.
@parambug@paramstep - One step, from direction4() or direction8().@paramarea - The square this bug is allowed to wander inside.
stepBug
(this.
Demo.bugB: {
    pos: Vector2i;
    trail: {};
}
bugB
,
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.direction8(): Vector2i
Returns one of the eight king-move unit directions (Y-down). Cardinals plus diagonals: `(±1, 0)`, `(0, ±1)`, `(±1, ±1)`.
@returnsNew unit vector.@since1.5.0
direction8
(), const BUG_AREA_B: Rect2iBUG_AREA_B);
} /** * Moves one bug by one step and remembers the position it left behind. * * @param {{ pos: Vector2i, trail: Array<Vector2i> }} bug * @param {Vector2i} step - One step, from direction4() or direction8(). * @param {Rect2i} area - The square this bug is allowed to wander inside. */
Demo.stepBug(bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}, step: Vector2i, area: Rect2i): void
Moves one bug by one step and remembers the position it left behind.
@parambug@paramstep - One step, from direction4() or direction8().@paramarea - The square this bug is allowed to wander inside.
stepBug
(
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
, step: Vector2i
- One step, from direction4() or direction8().
@paramstep - One step, from direction4() or direction8().
step
, area: Rect2i
- The square this bug is allowed to wander inside.
@paramarea - The square this bug is allowed to wander inside.
area
) {
// Remember where the bug was standing before it moved, so the trail grows behind it.
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.trail: Array<Vector2i>trail.push(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
(
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.pos: Vector2ipos.Vector2i.x: number
Horizontal component (defaults to 0).
x
,
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.pos: Vector2ipos.Vector2i.y: number
Vertical component (defaults to 0).
y
));
// Once the trail is long enough, drop the oldest position off the front. shift() // removes the first item in a list. if (
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.trail: Array<Vector2i>trail.length > const TRAIL_LENGTH: 90TRAIL_LENGTH) {
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.trail: Array<Vector2i>trail.shift();
} // Steps are 3 pixels so the trail is easy to see. clampInt keeps the bug from walking // out of its own square. // // The limits are pulled in twice over. The last pixel inside a square is one short of // its width, so a square 120 wide starting at x = 24 ends at x = 143. Then BUG_REACH // comes off each end as well, because the position is the middle of the marker rather // than its corner - without that the square would straddle the frame.
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.pos: Vector2ipos = 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
(
function clampInt(value: number, min: number, max: number): number
Clamps a whole number so it never leaves the range min..max. "Clamp" means "keep it inside the fence": if the value wandered past either end, this pushes it back to the nearest edge.
@paramvalue@parammin@parammax@returns
clampInt
(
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.pos: Vector2ipos.Vector2i.x: number
Horizontal component (defaults to 0).
x
+ step: Vector2i
- One step, from direction4() or direction8().
@paramstep - One step, from direction4() or direction8().
step
.Vector2i.x: number
Horizontal component (defaults to 0).
x
* 3, area: Rect2i
- The square this bug is allowed to wander inside.
@paramarea - The square this bug is allowed to wander inside.
area
.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
+ const BUG_REACH: 2BUG_REACH, area: Rect2i
- The square this bug is allowed to wander inside.
@paramarea - The square this bug is allowed to wander inside.
area
.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
+ area: Rect2i
- The square this bug is allowed to wander inside.
@paramarea - The square this bug is allowed to wander inside.
area
.Rect2i.width: number
Width in pixels (defaults to 0).
width
- 1 - const BUG_REACH: 2BUG_REACH),
function clampInt(value: number, min: number, max: number): number
Clamps a whole number so it never leaves the range min..max. "Clamp" means "keep it inside the fence": if the value wandered past either end, this pushes it back to the nearest edge.
@paramvalue@parammin@parammax@returns
clampInt
(
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.pos: Vector2ipos.Vector2i.y: number
Vertical component (defaults to 0).
y
+ step: Vector2i
- One step, from direction4() or direction8().
@paramstep - One step, from direction4() or direction8().
step
.Vector2i.y: number
Vertical component (defaults to 0).
y
* 3, area: Rect2i
- The square this bug is allowed to wander inside.
@paramarea - The square this bug is allowed to wander inside.
area
.Rect2i.y: number
Top edge Y coordinate (defaults to 0).
y
+ const BUG_REACH: 2BUG_REACH, area: Rect2i
- The square this bug is allowed to wander inside.
@paramarea - The square this bug is allowed to wander inside.
area
.Rect2i.y: number
Top edge Y coordinate (defaults to 0).
y
+ area: Rect2i
- The square this bug is allowed to wander inside.
@paramarea - The square this bug is allowed to wander inside.
area
.Rect2i.height: number
Height in pixels (defaults to 0).
height
- 1 - const BUG_REACH: 2BUG_REACH),
); } /** * Draws the two rows of cards. */ Demo.renderShuffle(): void
Draws the two rows of cards.
renderShuffle
() {
import uiui.caption(const CARD_LEFT: 22CARD_LEFT, 10, 'The list itself'); import uiui.caption(const CARD_LEFT: 22CARD_LEFT, 74, 'What shuffle() handed back', { color: stringcolor: 'dim' }); this.Demo.renderCardRow(cards: Array<number>, y: number): void
Draws one row of colored cards.
@paramcards - Card numbers, in the order they should appear.@paramy - Top edge of the row.
renderCardRow
(this.Demo.deck: {}deck, 24);
this.Demo.renderCardRow(cards: Array<number>, y: number): void
Draws one row of colored cards.
@paramcards - Card numbers, in the order they should appear.@paramy - Top edge of the row.
renderCardRow
(this.Demo.shuffled: {}shuffled, 88);
} /** * Draws one row of colored cards. * * @param {Array<number>} cards - Card numbers, in the order they should appear. * @param {number} y - Top edge of the row. */ Demo.renderCardRow(cards: Array<number>, y: number): void
Draws one row of colored cards.
@paramcards - Card numbers, in the order they should appear.@paramy - Top edge of the row.
renderCardRow
(cards: Array<number>
- Card numbers, in the order they should appear.
@paramcards - Card numbers, in the order they should appear.
cards
, y: number
- Top edge of the row.
@paramy - Top edge of the row.
y
) {
for (let let i: numberi = 0; let i: numberi < cards: Array<number>
- Card numbers, in the order they should appear.
@paramcards - Card numbers, in the order they should appear.
cards
.length; let i: numberi++) {
const const x: numberx = const CARD_LEFT: 22CARD_LEFT + let i: numberi * const CARD_STRIDE: 34CARD_STRIDE; // The card's number decides its color, so a card keeps its color wherever it moves. // That is what makes a reordering visible.
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
.drawRectFill: (rect: Rect2i, paletteIndex: number) => void
Draws a filled rectangle.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRectFill
(new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(const x: numberx, y: number
- Top edge of the row.
@paramy - Top edge of the row.
y
, const CARD_W: 26CARD_W, const CARD_H: 34CARD_H), const C_CARD_BASE: 10C_CARD_BASE + cards: Array<number>
- Card numbers, in the order they should appear.
@paramcards - Card numbers, in the order they should appear.
cards
[let i: numberi]);
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
.drawRect: (rect: Rect2i, paletteIndex: number) => void
Draws an unfilled rectangle outline.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRect
(new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(const x: numberx, y: number
- Top edge of the row.
@paramy - Top edge of the row.
y
, const CARD_W: 26CARD_W, const CARD_H: 34CARD_H), const C_INK: 2C_INK);
} } /** * Draws the chest, the falling gems, and the tier tally. */ Demo.renderWeighted(): void
Draws the chest, the falling gems, and the tier tally.
renderWeighted
() {
import uiui.caption(112, 8, 'Treasure chest'); // The chest itself is just a box - the interesting part is what comes out of it.
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
.drawRectFill: (rect: Rect2i, paletteIndex: number) => void
Draws a filled rectangle.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRectFill
(new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(140, 22, 40, 16), const C_DIM: 3C_DIM);
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
.drawRect: (rect: Rect2i, paletteIndex: number) => void
Draws an unfilled rectangle outline.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRect
(new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(140, 22, 40, 16), const C_INK: 2C_INK);
for (const const gem: anygem of this.Demo.gems: {}gems) {
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
.drawRectFill: (rect: Rect2i, paletteIndex: number) => void
Draws a filled rectangle.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRectFill
(new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(const gem: anygem.x, const gem: anygem.y, 6, 6), const C_TIER_BASE: 20C_TIER_BASE + const gem: anygem.tier);
} } /** * Draws the target and every arrow currently stuck in it. */ Demo.renderGaussian(): void
Draws the target and every arrow currently stuck in it.
renderGaussian
() {
import uiui.caption(96, 8, 'Aim for the middle'); // Concentric squares stand in for a round target - the engine draws rectangles, lines, // and pixels, so a "ring" here is a square outline. for (const const radius: anyradius of const TARGET_RINGS: {}TARGET_RINGS) {
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
.drawRect: (rect: Rect2i, paletteIndex: number) => void
Draws an unfilled rectangle outline.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRect
(
new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(const TARGET_CENTER: Vector2iTARGET_CENTER.Vector2i.x: number
Horizontal component (defaults to 0).
x
- const radius: anyradius, const TARGET_CENTER: Vector2iTARGET_CENTER.Vector2i.y: number
Vertical component (defaults to 0).
y
- const radius: anyradius, const radius: anyradius * 2, const radius: anyradius * 2),
const C_TARGET: 4C_TARGET, ); } for (const const shot: anyshot of this.Demo.shots: {}shots) {
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
.drawRectFill: (rect: Rect2i, paletteIndex: number) => void
Draws a filled rectangle.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRectFill
(new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(const shot: anyshot.x, const shot: anyshot.y, 2, 2), const shot: anyshot.wasGaussian ? const C_SHOT: 5C_SHOT : const C_SHOT_FLAT: 6C_SHOT_FLAT);
} } /** * Draws the walking line and the dot standing on it. */ Demo.renderSign(): void
Draws the walking line and the dot standing on it.
renderSign
() {
import uiui.caption(88, 50, 'Left or right, nothing else');
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
(const WALK_LEFT: 40WALK_LEFT, const WALK_Y: 88WALK_Y), 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 WALK_RIGHT: 280WALK_RIGHT, const WALK_Y: 88WALK_Y), const C_DIM: 3C_DIM);
// A tick mark at the starting point, so it is obvious how far the walker has drifted. const const start: numberstart = (const WALK_LEFT: 40WALK_LEFT + const WALK_RIGHT: 280WALK_RIGHT) / 2;
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
(const start: numberstart, const WALK_Y: 88WALK_Y - 6), 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 start: numberstart, const WALK_Y: 88WALK_Y + 6), const C_DIM: 3C_DIM);
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
.drawRectFill: (rect: Rect2i, paletteIndex: number) => void
Draws a filled rectangle.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRectFill
(new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(this.Demo.walkX: numberwalkX - 3, const WALK_Y: 88WALK_Y - 3, 7, 7), const C_INK: 2C_INK);
} /** * Draws both bugs and their trails. */ Demo.renderDirections(): void
Draws both bugs and their trails.
renderDirections
() {
import uiui.caption(const BUG_AREA_A: Rect2iBUG_AREA_A.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
, 12, '4 ways', { color: stringcolor: 'info' });
import uiui.caption(const BUG_AREA_B: Rect2iBUG_AREA_B.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
, 12, '8 ways', { color: stringcolor: 'warm' });
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
.drawRect: (rect: Rect2i, paletteIndex: number) => void
Draws an unfilled rectangle outline.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRect
(const BUG_AREA_A: Rect2iBUG_AREA_A, const C_DIM: 3C_DIM);
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
.drawRect: (rect: Rect2i, paletteIndex: number) => void
Draws an unfilled rectangle outline.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRect
(const BUG_AREA_B: Rect2iBUG_AREA_B, const C_DIM: 3C_DIM);
this.
Demo.renderBug(bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}, colorSlot: number): void
Draws one bug's trail as single pixels, then the bug itself as a small square.
@parambug@paramcolorSlot
renderBug
(this.
Demo.bugA: {
    pos: Vector2i;
    trail: {};
}
bugA
, const C_BUG_A: 7C_BUG_A);
this.
Demo.renderBug(bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}, colorSlot: number): void
Draws one bug's trail as single pixels, then the bug itself as a small square.
@parambug@paramcolorSlot
renderBug
(this.
Demo.bugB: {
    pos: Vector2i;
    trail: {};
}
bugB
, const C_BUG_B: 8C_BUG_B);
} /** * Draws one bug's trail as single pixels, then the bug itself as a small square. * * @param {{ pos: Vector2i, trail: Array<Vector2i> }} bug * @param {number} colorSlot */
Demo.renderBug(bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}, colorSlot: number): void
Draws one bug's trail as single pixels, then the bug itself as a small square.
@parambug@paramcolorSlot
renderBug
(
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
, colorSlot: number
@paramcolorSlot
colorSlot
) {
for (const const point: Array<Vector2i>point of
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.trail: Array<Vector2i>trail) {
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
.drawPixel: (posOrX: Vector2i | number, yOrColor: number, maybeColor?: number) => void
Draws a single pixel. Accepts either: - `(posOrX: Vector2i, yOrColor: number)` where `yOrColor` is the palette index. - `(posOrX: number, yOrColor: number, maybeColor: number)` for `(x, y, paletteIndex)`.
@since0.1.0@paramposOrX - Pixel position as `Vector2i`, or x coordinate when using numeric overload.@paramyOrColor - Palette index for vector overload, or y coordinate for numeric overload.@parammaybeColor - Palette index when using numeric overload.
drawPixel
(const point: Array<Vector2i>point, const C_DIM: 3C_DIM);
}
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
.drawRectFill: (rect: Rect2i, paletteIndex: number) => void
Draws a filled rectangle.
@since0.1.0@paramrect - Rectangle bounds in display coordinates.@parampaletteIndex - Palette color index.
drawRectFill
(new new Rect2i(x?: number, y?: number, width?: number, height?: number): Rect2i
Creates an integer rectangle, truncating all inputs toward zero.
@paramx - Left-edge X coordinate (defaults to 0).@paramy - Top-edge Y coordinate (defaults to 0).@paramwidth - Width in pixels (defaults to 0).@paramheight - Height in pixels (defaults to 0).
Rect2i
(
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.pos: Vector2ipos.Vector2i.x: number
Horizontal component (defaults to 0).
x
- const BUG_REACH: 2BUG_REACH,
bug: {
    pos: Vector2i;
    trail: Array<Vector2i>;
}
@parambug
bug
.pos: Vector2ipos.Vector2i.y: number
Vertical component (defaults to 0).
y
- const BUG_REACH: 2BUG_REACH, const BUG_SIZE: numberBUG_SIZE, const BUG_SIZE: numberBUG_SIZE), colorSlot: number
@paramcolorSlot
colorSlot
);
} /** * The two shuffle buttons, which are the whole lesson of this scene. */ Demo.renderShufflePanel(): void
The two shuffle buttons, which are the whole lesson of this scene.
renderShufflePanel
() {
import uiui.begin(import UI_ANCHORSUI_ANCHORS.BOTTOM_RIGHT); import uiui.panel('Shuffle'); if (import uiui.button('shuffle() a copy', { key: stringkey: 'KeyC' })) { // shuffle() builds a NEW mixed-up list and hands that back. The original list is // untouched, which is why the top row does not move when you press this. this.Demo.shuffled: {}shuffled =
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.shuffle<any>(arr: readonly any[]): any[]
Returns a new array with the same elements in shuffled order (Fisher-Yates).
@paramarr - Source array (not mutated).@returnsShuffled copy.@since1.5.0
shuffle
(this.Demo.deck: {}deck);
} if (import uiui.button('shuffleInPlace()', { key: stringkey: 'KeyP' })) { // shuffleInPlace() mixes up the list you handed it. The top row jumps, and the old // order is gone for good - there is no copy to go back to.
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
.random: Random
Default engine PRNG (live reference - not a copy). Time-seeded when the engine singleton is created. Call {@link BT.randomSeed } for a reproducible run. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@returnsThe shared {@link Random} instance.@exampleBT.randomSeed(42); BT.random.int(150, 420); BT.random.pick(['a', 'b', 'c']);
random
.Random.shuffleInPlace<any>(arr: any[]): any[]
Shuffles an array in place (Fisher-Yates) and returns it.
@paramarr - Array to mutate.@returnsThe same array reference.@since1.5.0
shuffleInPlace
(this.Demo.deck: {}deck);
} import uiui.separator(); import uiui.label('Copy leaves the top row alone.', { color: stringcolor: 'dim' }); import uiui.label('In place changes it for real.', { color: stringcolor: 'dim' }); import uiui.end(); } /** * The running tally of how often each tier has dropped. */ Demo.renderWeightedPanel(): void
The running tally of how often each tier has dropped.
renderWeightedPanel
() {
// Adding the counts up gives us something to measure each tier against. let let total: numbertotal = 0; for (const const count: anycount of this.Demo.tierCounts: {}tierCounts) { let total: numbertotal += const count: anycount; } import uiui.begin(import UI_ANCHORSUI_ANCHORS.BOTTOM_RIGHT); import uiui.panel('Drops so far'); for (let let i: numberi = 0; let i: numberi < const TIER_NAMES: {}TIER_NAMES.length; let i: numberi++) { // A meter wants a fraction from 0 to 1, so each count is divided by the total. // Guarding against a total of 0 avoids dividing by zero on the very first frame. const const share: numbershare = let total: numbertotal > 0 ? this.Demo.tierCounts: {}tierCounts[let i: numberi] / let total: numbertotal : 0; import uiui.meter(`${const TIER_NAMES: {}TIER_NAMES[let i: numberi]} ${this.Demo.tierCounts: {}tierCounts[let i: numberi]}`, const share: numbershare); } import uiui.separator(); import uiui.label(`Asked for 70 / 20 / 9 / 1`, { color: stringcolor: 'dim' }); import uiui.label(`Total drops: ${let total: numbertotal}`, { color: stringcolor: 'dim' }); import uiui.end(); } /** * The spread slider and the flat-versus-clumped switch. */ Demo.renderGaussianPanel(): void
The spread slider and the flat-versus-clumped switch.
renderGaussianPanel
() {
import uiui.begin(import UI_ANCHORSUI_ANCHORS.BOTTOM_RIGHT); import uiui.panel('Scatter'); this.Demo.useGaussian: booleanuseGaussian = import uiui.checkbox('Use gaussian()', this.Demo.useGaussian: booleanuseGaussian, { key: stringkey: 'KeyG' }); this.Demo.shotSpread: numbershotSpread = Math.round(import uiui.slider('Spread', this.Demo.shotSpread: numbershotSpread, { min: numbermin: 4, max: numbermax: 40 })); import uiui.separator(); if (this.Demo.useGaussian: booleanuseGaussian) { import uiui.label('Clumped near the middle.', { color: stringcolor: 'dim' }); } else { import uiui.label('Even, edge to edge.', { color: stringcolor: 'dim' }); } import uiui.label('Toggle it and watch.', { color: stringcolor: 'dim' }); import uiui.end(); } /** * How many times sign() answered each way. */ Demo.renderSignPanel(): void
How many times sign() answered each way.
renderSignPanel
() {
const const total: numbertotal = this.Demo.leftCount: numberleftCount + this.Demo.rightCount: numberrightCount; import uiui.begin(import UI_ANCHORSUI_ANCHORS.BOTTOM_RIGHT); import uiui.panel('Coin flips'); import uiui.kv('Left (-1)', this.Demo.leftCount: numberleftCount); import uiui.kv('Right (+1)', this.Demo.rightCount: numberrightCount); import uiui.kv('Total', const total: numbertotal); import uiui.separator(); import uiui.label('Close to even over time,', { color: stringcolor: 'dim' }); import uiui.label('but never exactly even.', { color: stringcolor: 'dim' }); import uiui.end(); } /** * A reminder of what separates the two bugs. */ Demo.renderDirectionsPanel(): void
A reminder of what separates the two bugs.
renderDirectionsPanel
() {
import uiui.begin(import UI_ANCHORSUI_ANCHORS.BOTTOM_RIGHT); import uiui.panel('Two bugs'); import uiui.label('Blue: direction4()', { color: stringcolor: 'info' }); import uiui.label('up, down, left, right', { color: stringcolor: 'dim' }); import uiui.spacer(4); import uiui.label('Orange: direction8()', { color: stringcolor: 'warm' }); import uiui.label('those four, plus diagonals', { color: stringcolor: 'dim' }); import uiui.separator(); import uiui.label('Both hand back a Vector2i.', { color: stringcolor: 'dim' }); import uiui.end(); } } 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
Five small scenes covering the parts of BT.random the other demos do not use.
@implementsIBTDemo
Demo
);