/*

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

Live version: https://demos.blit386.dev/random-basics

Guides:
  - Random: https://blit386.dev/docs/guides/random#deterministic-by-default

Reference:
  - Random: https://blit386.dev/docs/api/random#generators

---

WHAT YOU WILL SEE
-----------------

Five small scenes, one at a time, with the engine overlay turned off so they get the whole
screen. Every scene has the same bottom row: the "Scene 1/5" picker on the left, with Prev
and Next buttons marked with arrows (press 1-5 to jump straight to a scene), and that
scene's own panel on the right. Each scene shows one way of asking the engine for a
random answer:

  1. Shuffle - two rows of eight colored cards: the list itself, and a shuffled copy.
  2. Weighted - a treasure chest dropping gems in four colors, and a bar chart of every
     drop so far, with a white line on each bar at the share the code asked for.
  3. Gaussian - small squares landing near a target of four nested rings, not anywhere.
     The panel spells out the exact call each one makes.
  4. Sign - a dot walking along a line, stepping left or right on a coin flip, with the
     spots it stood on before trailing down underneath.
  5. Directions - two bugs wandering their own squares, one allowed 4 ways, the other 8.

WHAT YOU WILL LEARN
-------------------

- BT.random.shuffle(list) hands back a new mixed-up copy and leaves your list alone.
- BT.random.shuffleInPlace(list) mixes up the list you gave it, so the old order is gone.
- BT.random.weighted(items, weights) lets you say "this prize should show up 70 times as
  often as that one".
- BT.random.gaussian(mean, spread) clumps results near a middle value instead of spreading
  them evenly; BT.random.float(min, max) is the flat version, shown next to it to compare.
- BT.random.sign() answers -1 or 1, which is perfect for "which way?" questions.
- BT.random.direction4() and BT.random.direction8() hand back a ready-made step as a
  Vector2i.
- Counting update ticks and using the % remainder to act every few ticks instead of every
  single one.

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

TRY THIS
--------

- Press 1-5, or tap the Prev and Next buttons, to change scene.
- Scene 1: press C ("shuffle() a copy") and only the bottom row changes. Press P
  ("shuffleInPlace()") and the top row changes too - the old order is gone for good.
- Scene 2: wait a while, then compare each bar with its white line, and the "Got" row
  with the 70 / 20 / 9 / 1 the code asked for.
- Scene 3: press G or tap "Use gaussian()" to switch to float(). The green clump becomes
  an evenly filled red square. Drag the "Spread" slider (4 to 40) to tighten or widen it,
  and watch the call under it change.
- Scene 4: watch the "Coin flips" tally stay close to even, but never exactly even, and
  the trail under the line wander off to one side and back.
- Scene 5: compare the blocky blue trail (4 ways) with the rounder orange one (8 ways).

*/

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;
    ... 124 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 FONT_WFONT_W, import uiui } from './shared/ui.js'; /** @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 span // 264 pixels, so starting 28 pixels in centers the row on 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: 28CARD_LEFT = 28; // Top edges of the two card rows; each row's caption sits just above it. const const CARD_ROW_TOP_Y: 20CARD_ROW_TOP_Y = 20; const const CARD_ROW_BOTTOM_Y: 74CARD_ROW_BOTTOM_Y = 74; // 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 chest, where gems start falling from it, and the line where they disappear. const const CHEST_RECT: Rect2iCHEST_RECT = 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
(68, 20, 40, 16);
const const DROP_START_Y: 38DROP_START_Y = 38; const const DROP_FLOOR_Y: 112DROP_FLOOR_Y = 112; // The bar chart of drops so far: one bar per tier, as tall as that tier's share of all // drops (a 100% share would be BAR_MAX_H tall), with a faint line at the share the code // asked for. const const BAR_W: 20BAR_W = 20; const const BAR_GAP: 12BAR_GAP = 12; const const BAR_LEFT: 180BAR_LEFT = 180; const const BAR_BOTTOM_Y: 100BAR_BOTTOM_Y = 100; const const BAR_MAX_H: 80BAR_MAX_H = 80; // 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, 62);
const const TARGET_RINGS: {}TARGET_RINGS = [44, 33, 22, 11]; // The Sign scene walks a dot along this line, and draws where it stood on each of its // last WALK_HISTORY steps underneath, newest on top, WALK_HISTORY_GAP pixels apart. const const WALK_Y: 30WALK_Y = 30; const const WALK_LEFT: 40WALK_LEFT = 40; const const WALK_RIGHT: 280WALK_RIGHT = 280; const const WALK_HISTORY: 36WALK_HISTORY = 36; const const WALK_HISTORY_GAP: 2WALK_HISTORY_GAP = 2; // 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, 20, 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, 20, 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; // Screen layout. Every scene has the same bottom row: the scene picker on the left and // that scene's own panel on the right, both PANEL_H tall, so nothing jumps around when // you switch. The scene's picture fills the space above. const const PANEL_H: 111PANEL_H = 111; const const PANEL_Y: numberPANEL_Y = 240 - 4 - const PANEL_H: 111PANEL_H; const const NAV_PANEL_X: 4NAV_PANEL_X = 4; const const NAV_PANEL_W: 100NAV_PANEL_W = 100; const const SCENE_PANEL_X: 110SCENE_PANEL_X = 110; const const SCENE_PANEL_W: 206SCENE_PANEL_W = 206; // Widgets inside a panel are 20 pixels narrower than the panel itself. const const PANEL_CONTENT_SHRINK: 20PANEL_CONTENT_SHRINK = 20; const const NAV_BUTTON_W: numberNAV_BUTTON_W = const NAV_PANEL_W: 100NAV_PANEL_W - const PANEL_CONTENT_SHRINK: 20PANEL_CONTENT_SHRINK; const const SCENE_CONTENT_W: numberSCENE_CONTENT_W = const SCENE_PANEL_W: 206SCENE_PANEL_W - const PANEL_CONTENT_SHRINK: 20PANEL_CONTENT_SHRINK; // The scene panels' value column starts after this many characters, so the longest key, // "Right (+1)", keeps a space after it. const const SCENE_KV_COLS: 11SCENE_KV_COLS = 11; // Each scene panel's rows fall short of PANEL_H by a different amount. This much empty // space (index = MODE_* number) goes in just before each panel's closing note, so every // panel is the same height and the note always sits at its bottom. const const NOTE_GAP: {}NOTE_GAP = [4, 28, 18, 18, 24]; // The system font's arrows, for the Prev and Next buttons. const const ARROW_LEFT: "←"ARROW_LEFT = '\u2190'; const const ARROW_RIGHT: "→"ARROW_RIGHT = '\u2192'; // The x to print `text` at so its letters are centered on column `centerX`. The last // character's empty spacing column is left out, so the visible letters are what centers. function function centeredTextX(centerX: any, text: any): numbercenteredTextX(centerX: anycenterX, text: anytext) { return centerX: anycenterX - Math.floor((text: anytext.length * import FONT_WFONT_W - 1) / 2); } // 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. function function clampInt(value: any, min: any, max: any): anyclampInt(value: anyvalue, min: anymin, max: anymax) { if (value: anyvalue < min: anymin) { return min: anymin; } if (value: anyvalue > max: anymax) { return max: anymax; } return value: anyvalue; } // Five small scenes covering the parts of BT.random the other demos do not use. class class DemoDemo { /** @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. Keeping it apart from the copy // below is the whole point of this scene: one button changes only the copy, the other // button changes the list itself. Demo.deck: {}deck = []; // The copy that shuffle() handed back. Demo.shuffled: {}shuffled = []; // Weighted scene: how many of each tier have dropped so far. Demo.tierCounts: {}tierCounts = [0, 0, 0, 0]; // The gems currently falling. Demo.gems: {}gems = []; // Gaussian scene: a fixed-size ring of arrow positions. Demo.shots: {}shots = []; // Which slot the next arrow overwrites, so the oldest arrow quietly disappears // without any array shuffling. Demo.shotNext: numbershotNext = 0; // How far the arrows spread from the middle, set by the "Spread" slider. Demo.shotSpread: numbershotSpread = 18; // Whether arrows use gaussian() (clumped) or float() (flat). Demo.useGaussian: booleanuseGaussian = true; // Sign scene: where the walker stands. Demo.walkX: numberwalkX = (const WALK_LEFT: 40WALK_LEFT + const WALK_RIGHT: 280WALK_RIGHT) / 2; // How many times sign() has answered -1. Demo.leftCount: numberleftCount = 0; // How many times sign() has answered 1. Demo.rightCount: numberrightCount = 0; // Where the walker stood after each of its recent steps, newest first. Demo.walkHistory: {}walkHistory = []; // Directions scene: the 4-way 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: [] };
// The 8-way bug, same shape.
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: [] };
// Turns the engine overlay off: this demo needs the whole screen for its scenes and // panels, and has no timing or audio to watch.
Demo.configure(): {
    isOverlayEnabled: boolean;
}
configure
() {
return { isOverlayEnabled: booleanisOverlayEnabled: false, }; } // Builds the palette and fills in the starting state of every scene. async Demo.init(): unknowninit() { 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;
    ... 124 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: 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;
    ... 124 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(): voidupdate() { // 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;
    ... 124 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;
    ... 124 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;
    ... 124 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;
    ... 124 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;
    ... 124 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. The shuffle scene has // nothing to advance - its cards only move when a button is pressed. if (this.Demo.mode: numbermode === const MODE_WEIGHTED: 1MODE_WEIGHTED) { this.Demo.updateWeighted(): voidupdateWeighted(); } else if (this.Demo.mode: numbermode === const MODE_GAUSSIAN: 2MODE_GAUSSIAN) { this.Demo.updateGaussian(): voidupdateGaussian(); } else if (this.Demo.mode: numbermode === const MODE_SIGN: 3MODE_SIGN) { this.Demo.updateSign(): voidupdateSign(); } else if (this.Demo.mode: numbermode === const MODE_DIRECTIONS: 4MODE_DIRECTIONS) { this.Demo.updateDirections(): voidupdateDirections(); } } // Declares both panels, then draws the current scene above them. // // The panels come first because their buttons can change what the scene shows - a new // scene, a reshuffled deck - and the picture drawn after them should already show it. // They never overlap the picture, and the engine draws shapes like the cards and the // target under every panel anyway, so the order costs nothing on screen. Demo.render(): voidrender() {
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;
    ... 124 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);
this.Demo.renderNavPanel(): voidrenderNavPanel(); // Each scene adds its own controls and readouts in the panel beside the picker. import uiui.begin('topLeft', { x: numberx: const SCENE_PANEL_X: 110SCENE_PANEL_X, y: numbery: const PANEL_Y: numberPANEL_Y, width: numberwidth: const SCENE_PANEL_W: 206SCENE_PANEL_W, kvCols: numberkvCols: const SCENE_KV_COLS: 11SCENE_KV_COLS }); if (this.Demo.mode: numbermode === const MODE_SHUFFLE: 0MODE_SHUFFLE) { this.Demo.renderShufflePanel(): voidrenderShufflePanel(); } else if (this.Demo.mode: numbermode === const MODE_WEIGHTED: 1MODE_WEIGHTED) { this.Demo.renderWeightedPanel(): voidrenderWeightedPanel(); } else if (this.Demo.mode: numbermode === const MODE_GAUSSIAN: 2MODE_GAUSSIAN) { this.Demo.renderGaussianPanel(): voidrenderGaussianPanel(); } else if (this.Demo.mode: numbermode === const MODE_SIGN: 3MODE_SIGN) { this.Demo.renderSignPanel(): voidrenderSignPanel(); } else { this.Demo.renderDirectionsPanel(): voidrenderDirectionsPanel(); } import uiui.end(); if (this.Demo.mode: numbermode === const MODE_SHUFFLE: 0MODE_SHUFFLE) { this.Demo.renderShuffle(): voidrenderShuffle(); } else if (this.Demo.mode: numbermode === const MODE_WEIGHTED: 1MODE_WEIGHTED) { this.Demo.renderWeighted(): voidrenderWeighted(); } else if (this.Demo.mode: numbermode === const MODE_GAUSSIAN: 2MODE_GAUSSIAN) { this.Demo.renderGaussian(): voidrenderGaussian(); } else if (this.Demo.mode: numbermode === const MODE_SIGN: 3MODE_SIGN) { this.Demo.renderSign(): voidrenderSign(); } else { this.Demo.renderDirections(): voidrenderDirections(); } } // The scene picker, in the same spot in every scene. Two arrow buttons rather than // five named ones: five rows would not fit, and the number keys still jump straight // to a scene. The buttons are tappable, so someone on a phone can reach every scene // without a keyboard. Demo.renderNavPanel(): voidrenderNavPanel() { import uiui.begin('topLeft', { x: numberx: const NAV_PANEL_X: 4NAV_PANEL_X, y: numbery: const PANEL_Y: numberPANEL_Y, width: numberwidth: const NAV_PANEL_W: 100NAV_PANEL_W }); import uiui.panel(`Scene ${this.Demo.mode: numbermode + 1}/${const MODE_NAMES: {}MODE_NAMES.length}`); import uiui.label(const MODE_NAMES: {}MODE_NAMES[this.Demo.mode: numbermode], { color: stringcolor: 'accent' }); import uiui.label('or keys 1-5', { color: stringcolor: 'dim' }); import uiui.spacer(4); // Adding MODE_NAMES.length before taking the remainder keeps the answer positive // when stepping back from scene 1. if (import uiui.button(`${const ARROW_LEFT: "←"ARROW_LEFT} Prev`, { width: numberwidth: const NAV_BUTTON_W: numberNAV_BUTTON_W })) { 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 ${const ARROW_RIGHT: "→"ARROW_RIGHT}`, { width: numberwidth: const NAV_BUTTON_W: numberNAV_BUTTON_W })) { this.Demo.mode: numbermode = (this.Demo.mode: numbermode + 1) % const MODE_NAMES: {}MODE_NAMES.length; } import uiui.end(); } // Drops a new gem every few ticks and moves the falling ones down the screen. Demo.updateWeighted(): voidupdateWeighted() { // `%` is the remainder after dividing, so this is true once every 8 ticks. if (this.Demo.ticks: numberticks % const DROP_EVERY_TICKS: 8DROP_EVERY_TICKS === 0) { this.Demo.dropGem(): voiddropGem(); } // 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: 112DROP_FLOOR_Y) { this.Demo.gems: {}gems.splice(let i: numberi, 1); } } } // Asks weighted() for one treasure tier and starts a gem falling. Demo.dropGem(): voiddropGem() { // 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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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
(const CHEST_RECT: Rect2iCHEST_RECT.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
+ 4, const CHEST_RECT: Rect2iCHEST_RECT.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
+ const CHEST_RECT: Rect2iCHEST_RECT.Rect2i.width: number
Width in pixels (defaults to 0).
width
- 10),
y: numbery: const DROP_START_Y: 38DROP_START_Y, tier: anytier, }); } // Fires an arrow at the target every few ticks. Demo.updateGaussian(): voidupdateGaussian() { 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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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(): voidupdateSign() { 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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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++; } // Each step is 6 pixels; clampInt keeps the dot on the line. this.Demo.walkX: numberwalkX = function clampInt(value: any, min: any, max: any): anyclampInt(this.Demo.walkX: numberwalkX + const direction: 1 | -1direction * 6, const WALK_LEFT: 40WALK_LEFT, const WALK_RIGHT: 280WALK_RIGHT); // Remember the new spot at the front of the history, and let the oldest one fall // off the end. unshift() adds to the front of a list, pop() removes the last // item. this.Demo.walkHistory: {}walkHistory.unshift(this.Demo.walkX: numberwalkX); if (this.Demo.walkHistory: {}walkHistory.length > const WALK_HISTORY: 36WALK_HISTORY) { this.Demo.walkHistory: {}walkHistory.pop(); } } // Steps both bugs and records where they have been. Demo.updateDirections(): voidupdateDirections() { 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: any, step: any, area: any): voidstepBug(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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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: any, step: any, area: any): voidstepBug(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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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. `step` is one // step from direction4() or direction8(); `area` is the square this bug is allowed to // wander inside. Demo.stepBug(bug: any, step: any, area: any): voidstepBug(bug: anybug, step: anystep, area: anyarea) { // Remember where the bug was standing before it moved, so the trail grows behind // it. bug: anybug.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: anybug.pos.x, bug: anybug.pos.y));
// Once the trail is long enough, drop the oldest position off the front. shift() // removes the first item in a list. if (bug: anybug.trail.length > const TRAIL_LENGTH: 90TRAIL_LENGTH) { bug: anybug.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: anybug.pos = 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: any, min: any, max: any): anyclampInt(bug: anybug.pos.x + step: anystep.x * 3, area: anyarea.x + const BUG_REACH: 2BUG_REACH, area: anyarea.x + area: anyarea.width - 1 - const BUG_REACH: 2BUG_REACH), function clampInt(value: any, min: any, max: any): anyclampInt(bug: anybug.pos.y + step: anystep.y * 3, area: anyarea.y + const BUG_REACH: 2BUG_REACH, area: anyarea.y + area: anyarea.height - 1 - const BUG_REACH: 2BUG_REACH), ); } // Draws the two rows of cards. Demo.renderShuffle(): voidrenderShuffle() { import uiui.caption(const CARD_LEFT: 28CARD_LEFT, const CARD_ROW_TOP_Y: 20CARD_ROW_TOP_Y - 10, 'The list itself'); import uiui.caption(const CARD_LEFT: 28CARD_LEFT, const CARD_ROW_BOTTOM_Y: 74CARD_ROW_BOTTOM_Y - 10, 'What shuffle() handed back', { color: stringcolor: 'dim' }); this.Demo.renderCardRow(cards: any, y: any): voidrenderCardRow(this.Demo.deck: {}deck, const CARD_ROW_TOP_Y: 20CARD_ROW_TOP_Y); this.Demo.renderCardRow(cards: any, y: any): voidrenderCardRow(this.Demo.shuffled: {}shuffled, const CARD_ROW_BOTTOM_Y: 74CARD_ROW_BOTTOM_Y); } // Draws one row of colored cards. `cards` holds the card numbers in the order they // should appear; `y` is the top edge of the row. Demo.renderCardRow(cards: any, y: any): voidrenderCardRow(cards: anycards, y: anyy) { for (let let i: numberi = 0; let i: numberi < cards: anycards.length; let i: numberi++) { const const x: numberx = const CARD_LEFT: 28CARD_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;
    ... 124 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: anyy, const CARD_W: 26CARD_W, const CARD_H: 34CARD_H), const C_CARD_BASE: 10C_CARD_BASE + cards: anycards[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;
    ... 124 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: anyy, const CARD_W: 26CARD_W, const CARD_H: 34CARD_H), const C_INK: 2C_INK);
} } // Draws the chest and the falling gems on the left, and a bar chart of every drop so // far on the right. Demo.renderWeighted(): voidrenderWeighted() { const const chestMidX: anychestMidX = const CHEST_RECT: Rect2iCHEST_RECT.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
+ Math.floor(const CHEST_RECT: Rect2iCHEST_RECT.Rect2i.width: number
Width in pixels (defaults to 0).
width
/ 2);
import uiui.caption(function centeredTextX(centerX: any, text: any): numbercenteredTextX(const chestMidX: anychestMidX, 'Treasure chest'), const CHEST_RECT: Rect2iCHEST_RECT.Rect2i.y: number
Top edge Y coordinate (defaults to 0).
y
- 10, '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;
    ... 124 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
(const CHEST_RECT: Rect2iCHEST_RECT, 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;
    ... 124 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 CHEST_RECT: Rect2iCHEST_RECT, const C_INK: 2C_INK);
// Each gem is a 6x6 square in its tier's color. 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;
    ... 124 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);
} this.Demo.renderDropChart(): voidrenderDropChart(); } // One bar per tier, as tall as that tier's share of all drops, with a faint line at // the share the weights asked for. Above each bar, its share in percent; under it, // the tier's first letter. Demo.renderDropChart(): voidrenderDropChart() { const const total: anytotal = this.Demo.totalDrops(): anytotalDrops(); const const chartW: numberchartW = const TIER_NAMES: {}TIER_NAMES.length * const BAR_W: 20BAR_W + (const TIER_NAMES: {}TIER_NAMES.length - 1) * const BAR_GAP: 12BAR_GAP; const const weightSum: anyweightSum = const TIER_WEIGHTS: {}TIER_WEIGHTS.reduce((sum: anysum, weight: anyweight) => sum: anysum + weight: anyweight, 0); import uiui.caption(function centeredTextX(centerX: any, text: any): numbercenteredTextX(const BAR_LEFT: 180BAR_LEFT + Math.floor(const chartW: numberchartW / 2), 'Drops so far'), const CHEST_RECT: Rect2iCHEST_RECT.Rect2i.y: number
Top edge Y coordinate (defaults to 0).
y
- 10, 'Drops so far');
// The floor of the chart.
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;
    ... 124 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 BAR_LEFT: 180BAR_LEFT - 4, const BAR_BOTTOM_Y: 100BAR_BOTTOM_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 BAR_LEFT: 180BAR_LEFT + const chartW: numberchartW + 3, const BAR_BOTTOM_Y: 100BAR_BOTTOM_Y), const C_DIM: 3C_DIM);
for (let let i: numberi = 0; let i: numberi < const TIER_NAMES: {}TIER_NAMES.length; let i: numberi++) { const const x: numberx = const BAR_LEFT: 180BAR_LEFT + let i: numberi * (const BAR_W: 20BAR_W + const BAR_GAP: 12BAR_GAP); const const midX: anymidX = const x: numberx + Math.floor(const BAR_W: 20BAR_W / 2); // A share is a fraction from 0 to 1, so a 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 = const total: anytotal > 0 ? this.Demo.tierCounts: {}tierCounts[let i: numberi] / const total: anytotal : 0; const const barH: anybarH = Math.round(const share: numbershare * const BAR_MAX_H: 80BAR_MAX_H); const const askedY: numberaskedY = const BAR_BOTTOM_Y: 100BAR_BOTTOM_Y - Math.round((const TIER_WEIGHTS: {}TIER_WEIGHTS[let i: numberi] / const weightSum: anyweightSum) * const BAR_MAX_H: 80BAR_MAX_H); if (const barH: anybarH > 0) {
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;
    ... 124 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, const BAR_BOTTOM_Y: 100BAR_BOTTOM_Y - const barH: anybarH, const BAR_W: 20BAR_W, const barH: anybarH), const C_TIER_BASE: 20C_TIER_BASE + let i: numberi);
} // The asked-for share, drawn over the bar so it shows either way.
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;
    ... 124 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 x: numberx - 2, const askedY: numberaskedY), 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 x: numberx + const BAR_W: 20BAR_W + 1, const askedY: numberaskedY), const C_INK: 2C_INK);
// The percent sits above whichever is higher, the bar or its white line. const const percent: stringpercent = `${Math.round(const share: numbershare * 100)}%`; const const labelBottom: anylabelBottom = Math.min(const BAR_BOTTOM_Y: 100BAR_BOTTOM_Y - const barH: anybarH, const askedY: numberaskedY); import uiui.caption(function centeredTextX(centerX: any, text: any): numbercenteredTextX(const midX: anymidX, const percent: stringpercent), const labelBottom: anylabelBottom - 10, const percent: stringpercent, { color: stringcolor: 'dim' }); import uiui.caption(function centeredTextX(centerX: any, text: any): numbercenteredTextX(const midX: anymidX, const TIER_NAMES: {}TIER_NAMES[let i: numberi][0]), const BAR_BOTTOM_Y: 100BAR_BOTTOM_Y + 5, const TIER_NAMES: {}TIER_NAMES[let i: numberi][0], { color: stringcolor: 'dim' }); } } // Draws the target and every arrow currently stuck in it. Demo.renderGaussian(): voidrenderGaussian() { const const ringTop: numberringTop = const TARGET_CENTER: Vector2iTARGET_CENTER.Vector2i.y: number
Vertical component (defaults to 0).
y
- const TARGET_RINGS: {}TARGET_RINGS[0];
import uiui.caption(function centeredTextX(centerX: any, text: any): numbercenteredTextX(const TARGET_CENTER: Vector2iTARGET_CENTER.Vector2i.x: number
Horizontal component (defaults to 0).
x
, 'Aim for the middle'), const ringTop: numberringTop - 10, '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;
    ... 124 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, ); } // Each arrow is a 2x2 square, green for gaussian() and red for float(). 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;
    ... 124 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 with the dot standing on it, and under it a column of the // spots the dot stood on before - newest on top, so the walk reads downward in time. Demo.renderSign(): voidrenderSign() { const const start: numberstart = (const WALK_LEFT: 40WALK_LEFT + const WALK_RIGHT: 280WALK_RIGHT) / 2; const const label: "Left or right, nothing else"label = 'Left or right, nothing else'; import uiui.caption(function centeredTextX(centerX: any, text: any): numbercenteredTextX(const start: numberstart, const label: "Left or right, nothing else"label), const WALK_Y: 30WALK_Y - 22, const label: "Left or right, nothing else"label);
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;
    ... 124 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: 30WALK_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: 30WALK_Y), const C_DIM: 3C_DIM);
// A tick mark at the starting point, so it is obvious how far the walker has // drifted, and the two ends labeled with what sign() answers to get there.
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;
    ... 124 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: 30WALK_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: 30WALK_Y + 6), const C_DIM: 3C_DIM);
import uiui.caption(const WALK_LEFT: 40WALK_LEFT - 2 * import FONT_WFONT_W - 6, const WALK_Y: 30WALK_Y - 2, '-1', { color: stringcolor: 'dim' }); import uiui.caption(const WALK_RIGHT: 280WALK_RIGHT + 7, const WALK_Y: 30WALK_Y - 2, '+1', { color: stringcolor: 'dim' }); // The history: one pixel per past step, under the line. for (let let i: numberi = 0; let i: numberi < this.Demo.walkHistory: {}walkHistory.length; 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;
    ... 124 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
(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
(this.Demo.walkHistory: {}walkHistory[let i: numberi], const WALK_Y: 30WALK_Y + 10 + let i: numberi * const WALK_HISTORY_GAP: 2WALK_HISTORY_GAP), const C_DIM: 3C_DIM);
} // The walker: a 7x7 square centered on the line.
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;
    ... 124 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: 30WALK_Y - 3, 7, 7), const C_INK: 2C_INK);
} // Draws both bugs and their trails. Demo.renderDirections(): voidrenderDirections() { import uiui.caption(const BUG_AREA_A: Rect2iBUG_AREA_A.Rect2i.x: number
Left edge X coordinate (defaults to 0).
x
, const BUG_AREA_A: Rect2iBUG_AREA_A.Rect2i.y: number
Top edge Y coordinate (defaults to 0).
y
- 10, '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
, const BUG_AREA_B: Rect2iBUG_AREA_B.Rect2i.y: number
Top edge Y coordinate (defaults to 0).
y
- 10, '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;
    ... 124 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;
    ... 124 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: any, colorSlot: any): voidrenderBug(this.
Demo.bugA: {
    pos: Vector2i;
    trail: {};
}
bugA
, const C_BUG_A: 7C_BUG_A);
this.Demo.renderBug(bug: any, colorSlot: any): voidrenderBug(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. Demo.renderBug(bug: any, colorSlot: any): voidrenderBug(bug: anybug, colorSlot: anycolorSlot) { for (const const point: anypoint of bug: anybug.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;
    ... 124 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: anypoint, 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;
    ... 124 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: anybug.pos.x - const BUG_REACH: 2BUG_REACH, bug: anybug.pos.y - const BUG_REACH: 2BUG_REACH, const BUG_SIZE: numberBUG_SIZE, const BUG_SIZE: numberBUG_SIZE), colorSlot: anycolorSlot);
} // How many gems have dropped so far, all tiers together. Demo.totalDrops(): anytotalDrops() { return this.Demo.tierCounts: {}tierCounts.reduce((sum: anysum, count: anycount) => sum: anysum + count: anycount, 0); } // The two shuffle buttons, which are the whole lesson of this scene. Like every // scene panel, this one only declares rows: render() opens and closes the group. Demo.renderShufflePanel(): voidrenderShufflePanel() { import uiui.panel('Shuffle'); if (import uiui.button('C - shuffle() a copy', { key: stringkey: 'KeyC', width: numberwidth: const SCENE_CONTENT_W: numberSCENE_CONTENT_W })) { // 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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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('P - shuffleInPlace()', { key: stringkey: 'KeyP', width: numberwidth: const SCENE_CONTENT_W: numberSCENE_CONTENT_W })) { // 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;
    ... 124 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, or open the page with `?seed=N` - applied in `BT.init()` just before the demo's own `init()`, so a `randomSeed` call there still wins. Mutating the instance (for example `BT.random.int(10)`) advances the shared stream.
@since1.5.0@changed1.7.1 `?seed=N` URL parameter seeds the shared generator before the demo's `init()`.@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.spacer(const NOTE_GAP: {}NOTE_GAP[const MODE_SHUFFLE: 0MODE_SHUFFLE]); import uiui.label('Copy: the top row stays put.', { color: stringcolor: 'dim' }); import uiui.label('In place: the top row moves.', { color: stringcolor: 'dim' }); } // The weights the code asked for, the shares that actually dropped, and the total. Demo.renderWeightedPanel(): voidrenderWeightedPanel() { const const total: anytotal = this.Demo.totalDrops(): anytotalDrops(); // Each tier's share of all drops in whole percent, joined with slashes to line up // with the asked-for row above it. const const got: anygot = this.Demo.tierCounts: {}tierCounts.map((count: anycount) => (const total: anytotal > 0 ? Math.round((count: anycount / const total: anytotal) * 100) : 0)).join(' / '); import uiui.panel('Weighted drops'); import uiui.kv('Asked', const TIER_WEIGHTS: {}TIER_WEIGHTS.join(' / ')); import uiui.kv('Got', const got: anygot); import uiui.kv('Drops', const total: anytotal); import uiui.spacer(const NOTE_GAP: {}NOTE_GAP[const MODE_WEIGHTED: 1MODE_WEIGHTED]); import uiui.label('The white lines mark what the', { color: stringcolor: 'dim' }); import uiui.label('weights asked for. Rare is rare.', { color: stringcolor: 'dim' }); } // The flat-versus-clumped switch and the spread slider. Demo.renderGaussianPanel(): voidrenderGaussianPanel() { import uiui.panel('Scatter'); // The checkbox answers true or false; the slider answers a number, rounded to a // whole pixel and shown without decimals. this.Demo.useGaussian: booleanuseGaussian = import uiui.checkbox('G - Use gaussian()', this.Demo.useGaussian: booleanuseGaussian, { key: stringkey: 'KeyG' }); import uiui.spacer(4); this.Demo.shotSpread: numbershotSpread = Math.round( import uiui.slider('Spread', this.Demo.shotSpread: numbershotSpread, { min: numbermin: 4, max: numbermax: 40, width: numberwidth: const SCENE_CONTENT_W: numberSCENE_CONTENT_W, decimals: numberdecimals: 0 }), ); // The exact call each arrow makes right now, with this spread filled in. const const reach: numberreach = this.Demo.shotSpread: numbershotSpread * 2; const const call: stringcall = this.Demo.useGaussian: booleanuseGaussian ? `gaussian(0, ${this.Demo.shotSpread: numbershotSpread})` : `float(-${const reach: numberreach}, ${const reach: numberreach})`; import uiui.label(`Each arrow: ${const call: stringcall}`, { color: stringcolor: 'info' }); import uiui.spacer(const NOTE_GAP: {}NOTE_GAP[const MODE_GAUSSIAN: 2MODE_GAUSSIAN]); import uiui.label(this.Demo.useGaussian: booleanuseGaussian ? 'Green: clumped near the middle.' : 'Red: even, edge to edge.', { color: stringcolor: 'dim', }); } // How many times sign() answered each way. Demo.renderSignPanel(): voidrenderSignPanel() { 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', this.Demo.leftCount: numberleftCount + this.Demo.rightCount: numberrightCount); // How far the walker has drifted from the tick mark, in 6-pixel steps. const const drift: numberdrift = (this.Demo.walkX: numberwalkX - (const WALK_LEFT: 40WALK_LEFT + const WALK_RIGHT: 280WALK_RIGHT) / 2) / 6; import uiui.kv('Drift', `${const drift: numberdrift > 0 ? '+' : ''}${const drift: numberdrift} steps`); import uiui.spacer(const NOTE_GAP: {}NOTE_GAP[const MODE_SIGN: 3MODE_SIGN]); import uiui.label('Close to even over time,', { color: stringcolor: 'dim' }); import uiui.label('but never exactly even.', { color: stringcolor: 'dim' }); } // A reminder of what separates the two bugs. Demo.renderDirectionsPanel(): voidrenderDirectionsPanel() { 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.spacer(const NOTE_GAP: {}NOTE_GAP[const MODE_DIRECTIONS: 4MODE_DIRECTIONS]); import uiui.label('Both hand back a Vector2i.', { color: stringcolor: 'dim' }); } } 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 DemoDemo);