@beetpx/beetpx
Version:
A TypeScript framework for pixel art browser games.
1,701 lines (1,673 loc) • 102 kB
TypeScript
import { PngDataArray } from 'fast-png';
/**
* @see {@link BpxImageAsset}
*
* @category Assets
*/
type BpxImageUrl = string;
/**
* @see {@link BpxSoundAsset}
*
* @category Assets
*/
type BpxSoundUrl = string;
/**
* @see {@link BpxJsonAsset}
*
* @category Assets
*/
type BpxJsonUrl = string;
/**
* @example
* ```ts
* const sprite1Url: BpxImageUrl = "spritesheet.png"; // refers to `./public/spritesheet.png`
* const sprite2Url: BpxImageUrl = "https://the.url/of/another-spritesheet.png";
*
* let sprite1: BpxSprite;
* let sprite2: BpxSprite;
*
* $x.setOnStarted(() => {
* sprite1 = $spr(sprite1Url)(8,8,0,0);
* sprite2 = $spr(sprite2Url)(8,8,0,0);
* });
*
* $x.start({
* // ...,
* assets: [
* sprite1Url,
* sprite2Url,
* ],
* });
* ```
*
* @category Assets
*/
type BpxImageAsset = {
/**
* Image's width in pixels.
*/
width: number;
/**
* Image's height in pixels.
*/
height: number;
/**
* Number of image channels.
*/
channels: 3 | 4;
/**
* The actual image data.
*/
rgba8bitData: PngDataArray;
};
/**
* @example
* ```ts
* const musicUrl: BpxSoundUrl = "music.flac"; // refers to `./public/music.flac`
* const sfxUrl: BpxSoundUrl = "https://the.url/of/sfx.wav";
*
* let playback1: BpxAudioPlaybackId;
* let playback2: BpxAudioPlaybackId;
*
* $x.setOnStarted(() => {
* playback1 = $x.startPlayback(musicUrl);
* playback2 = $x.startPlayback(sfxUrl);
* });
*
* $x.start({
* // ...,
* assets: [
* musicUrl,
* sfxUrl,
* ],
* });
* ```
*
* @category Assets
*/
type BpxSoundAsset = {
/**
* The actual sound data.
*/
audioBuffer: AudioBuffer;
};
/**
* @example
* ```ts
* const statsUrl: BpxJsonUrl = "level.ldtk"; // refers to `./public/stats.json`
* const levelUrl: BpxJsonUrl = "https://the.url/of/level.ldtk";
*
* let stats: BpxJsonAsset;
* let level: BpxJsonAsset;
*
* $x.setOnStarted(() => {
* const stats: BpxJsonAsset = $x.getJsonAsset(statsUrl);
* const level: BpxJsonAsset = $x.getJsonAsset(levelUrl);
* });
*
* $x.start({
* // ...,
* assets: [
* statsUrl,
* levelUrl,
* ],
* });
* ```
*
* @category Assets
*/
type BpxJsonAsset = {
/**
* A content of the fetched JSON file.
*/
json: any;
};
/**
* @see {@link BpxFrameworkConfig}'s `assets`
*
* @category Assets
*/
type BpxAssetsToLoad = Array<BpxImageUrl | BpxSoundUrl | BpxJsonUrl>;
/**
* An identifier of a played audio. Can be used to e.g. mute a specific sound.
*
* @see {@link BeetPx.startPlayback}
* @see {@link BeetPx.startPlaybackLooped}
* @see {@link BeetPx.startPlaybackSequence}
*
* @category Audio
*/
type BpxAudioPlaybackId = number;
/**
* A definition of a sequence of sounds to be played. A typical use case would be
* to define a music which consist of an intro phase, then loops indefinitely. Another
* use case is to recreate the music composed in PICO-8 – it usually is built from
* many short samples, tied together. Moreover, the `BpxSoundSequence` allows to
* crop the sample, which might be useful for a PICO-8 music composed of samples
* shorter than default 32 bits, but exported as 33-bits long.
*
* @example
* ```ts
* const halfDuration = (fullSoundDurationMs: number) => fullSoundDurationMs * 16 / 32;
* $x.startPlaybackSequence({
* intro: [
* [{ url: "intro1Melody.flac", durationMs: halfDuration }],
* [{ url: "intro2Melody.flac", durationMs: halfDuration }, { url: "intro2Bass.flac" }],
* ],
* loop: [
* ["loop1Melody.flac", "loop1Bass.flac"],
* ["loop2Melody.flac", "loop2Bass.flac"],
* ["loop3Melody.flac", "loop3Bass.flac"],
* ],
* });
* ```
*
* @category Audio
*/
type BpxSoundSequence = {
intro?: BpxSoundSequenceEntry[];
loop?: BpxSoundSequenceEntry[];
};
/**
* @see {@link BpxSoundSequence}
*
* @category Audio
*/
type BpxSoundSequenceEntry = [
BpxSoundSequenceEntrySoundMain,
...BpxSoundSequenceEntrySoundAdditional[]
];
/**
* @see {@link BpxSoundSequence}
*
* @category Audio
*/
type BpxSoundSequenceEntrySoundMain = BpxSoundUrl | {
url: BpxSoundUrl;
durationMs?: (fullSoundDurationMs: number) => number;
};
/**
* @see {@link BpxSoundSequence}
*
* @category Audio
*/
type BpxSoundSequenceEntrySoundAdditional = BpxSoundUrl | {
url: BpxSoundUrl;
};
/**
* The list of browser types the framework detects.
* It is tightly related to the gamepad mapping detection.
*
* @see {@link BeetPx.detectedBrowserType}
*
* @category Game input
*/
type BpxBrowserType = "chromium" | "firefox_windows" | "firefox_other" | "safari" | "other";
/**
* @see {@link BpxRgbColor}
*
* @category Colors
*/
type BpxRgbCssHex = string;
/**
* A representation of a RGB, fully opaque color
*
* @category Colors
*/
declare class BpxRgbColor {
/**
* @example
* ```ts
* BpxRgbColor.of(255, 0, 77);
* ```
*
* @group Static factories
*/
static of(r: number, g: number, b: number): BpxRgbColor;
/**
* @example
* ```ts
* BpxRgbColor.fromCssHex("#FF004D");
* ```
*
* @group Static factories
*/
static fromCssHex(cssHex: BpxRgbCssHex): BpxRgbColor;
/**
* A property helpful for TypeScript type inference, when distinguishing from
* other types of colors.
*
* @example
* ```ts
* const c:
* | null
* | BpxRgbColor
* | BpxPatternColors
* | BpxSpriteColorMapping
* | BpxCanvasSnapshotColorMapping
* = getColor();
* if (c == null) {
* // c is transparent here
* } else if (c.type === "rgb") {
* // c is BpxRgbColor here
* } else if (c.type === "pattern") {
* // c is BpxPatternColors here
* } else if (c.type === "sprite_mapping") {
* // c is BpxSpriteColorMapping here
* } else if (c.type === "canvas_snapshot_mapping") {
* // c is BpxCanvasSnapshotColorMapping here
* } else {
* $u.assertUnreachable(c);
* }
* ```
*/
readonly type = "rgb";
/**
* A red component, an integer between 0 and 255.
*/
readonly r: number;
/**
A green component, an integer between 0 and 255.
*/
readonly g: number;
/**
A blue component, an integer between 0 and 255.
*/
readonly b: number;
/**
* A hex representation of this color. Can be used e.g. for CSS.
* Or just for simple way to store a color as a single value.
*/
readonly cssHex: BpxRgbCssHex;
private constructor();
/**
* Checks if this color has same red, green, and blue components as the other one.
*/
isSameAs(another: BpxRgbColor): boolean;
/**
* Returns an array containing red, green, and blue components of this color.
*/
asArray(): [r: number, g: number, b: number];
}
/**
* @see {@link BpxCanvasSnapshotColorMapping.getMappedColor}
*
* @category Drawing
*/
interface BpxCanvasSnapshot {
getColorAt(x: number, y: number): BpxRgbColor;
}
/**
* @see {@link BpxSpriteColorMapping}
* @see {@link BpxCanvasSnapshotColorMapping}
*
* @category Drawing
*/
type BpxColorMapper = (sourceColor: BpxRgbColor | null, x?: number, y?: number) => BpxRgbColor | null;
/**
* An interface to extend if you want to define `__printDebug()` – a convenience method used by
* the internal logger to print objects in a custom way. An example is built-in
* {@link BpxVector2d} type which defined `__printDebug()` in order to be printed
* by the logger in a `(x,y)` format.
*
* @see {@link BeetPx.logDebug}
* @see {@link BeetPx.logInfo}
* @see {@link BeetPx.logWarn}
* @see {@link BeetPx.logError}
*
* @category Debug
*/
interface BpxPrintDebug {
__printDebug(): string;
}
/**
* A core building block for many pieces of the BeetPx API – a vector, which is 2D point representation of (X,Y).
*
* @category Core
*/
declare class BpxVector2d implements BpxPrintDebug {
/**
* The X component of the vector.
*/
readonly x: number;
/**
* The X component of the vector.
*/
readonly y: number;
/**
* @param turnAngle A full circle turn = 1. In other words: 0 deg = 0 turn, 90 deg = 0.25 turn, 180 deg = 0.5 turn, 270 deg = 0.75 turn.
*
* @returns A vector of a length 1, angled according to a given `turnAngle`. E.g. `(0, -1)` for an angle of `-0.25`.
*
* @group Static factories
*/
static unitFromAngle(turnAngle: number): BpxVector2d;
/**
* An equivalent of `BpxVector2d.of(value, value)`.
*
* @group Static factories
*/
static of(value: number): BpxVector2d;
/**
* @group Static factories
*/
static of(x: number, y: number): BpxVector2d;
private constructor();
/**
* Creates a vector which has the lowest X and Y from two other given vectors.
*
* @group Static factories
*/
static minOf(xy1: BpxVector2d, xy2: BpxVector2d): BpxVector2d;
/**
* Creates a vector which has the highest X and Y from two other given vectors.
*
* @group Static factories
*/
static maxOf(xy1: BpxVector2d, xy2: BpxVector2d): BpxVector2d;
/**
* An equivalent of `[BpxVector2d.minOf(xy1, xy2), BpxVector2d.maxOf(xy1, xy2)]`.
*
* @example
* ```ts
* const [minV, maxV] = BpxVector2d.minMaxOf(v1, v2);
* ```
*
* @group Static factories
*/
static minMaxOf(xy1: BpxVector2d, xy2: BpxVector2d): [BpxVector2d, BpxVector2d];
/**
* Creates a vector with X and Y passed through the {@link BeetPxUtils.lerp} individually.
*
* @group Static factories
*/
static lerp(xy1: BpxVector2d, xy2: BpxVector2d, t: number, opts?: {
clamp?: boolean;
}): BpxVector2d;
/**
* @returns An array of `[x, y]`.
*/
asArray(): [number, number];
/**
* @returns A magnitude (length) of the vector, which is `sqrt(x^2 + y^2)`.
*/
magnitude(): number;
/**
* @returns A vector of same angle, but of length 1. Or 0, if the original vector was 0.
*/
normalize(): BpxVector2d;
/**
* @returns A vector in which each component is either `-1`, `0`, or `1` to indicate the sign of the original value.
*/
sign(): BpxVector2d;
/**
* @returns A vector in which each component is an absolute value of the original value.
*/
abs(): BpxVector2d;
/**
* @returns A vector in which each component is a negative of the original value.
*/
neg(): BpxVector2d;
/**
* @returns A vector in which each component is a floor rounding of the original value.
*/
floor(): BpxVector2d;
/**
* @returns A vector in which each component is a ceil rounding of the original value.
*/
ceil(): BpxVector2d;
/**
* @returns A vector in which each component is a rounding of the original value.
*/
round(): BpxVector2d;
/**
* This method is an equivalent of calling {@link BeetPxUtils.trigAtan2} with both `x` and `y` of this vector as the params.
*
* @returns The "turn" of the vector. A full circle turn = 1. In other words: 0 deg = 0 turn, 90 deg = 0.25 turn, 180 deg = 0.5 turn, 270 deg = 0.75 turn.
*/
toAngle(): number;
/**
* @returns If the vector has both of its components equal to the same components of a given vector.
*/
eq(other: BpxVector2d): boolean;
/**
* @returns If the vector has both of its components equal to a given value.
*/
eq(value: number): boolean;
/**
* @returns If the vector has both of its components equal to a given x and y.
*/
eq(x: number, y: number): boolean;
/**
* @returns If the vector has both of its components greater than the same components of a given vector.
*/
gt(other: BpxVector2d): boolean;
/**
* @returns If the vector has both of its components greater than a given value.
*/
gt(value: number): boolean;
/**
* @returns If the vector has both of its components greater than a given x and y.
*/
gt(x: number, y: number): boolean;
/**
* @returns If the vector has both of its components greater or equal to the same components of a given vector.
*/
gte(other: BpxVector2d): boolean;
/**
* @returns If the vector has both of its components greater or equal to a given value.
*/
gte(value: number): boolean;
/**
* @returns If the vector has both of its components greater or equal to a given x and y.
*/
gte(x: number, y: number): boolean;
/**
* @returns If the vector has both of its components lower than the same components of a given vector.
*/
lt(other: BpxVector2d): boolean;
/**
* @returns If the vector has both of its components lower than a given value.
*/
lt(value: number): boolean;
/**
* @returns If the vector has both of its components lower than a given x and y.
*/
lt(x: number, y: number): boolean;
/**
* @returns If the vector has both of its components lower or equal to the same components of a given vector.
*/
lte(other: BpxVector2d): boolean;
/**
* @returns If the vector has both of its components lower or equal to a given value.
*/
lte(value: number): boolean;
/**
* @returns If the vector has both of its components lower or equal to a given x and y.
*/
lte(x: number, y: number): boolean;
/**
* @returns Creates a vector with X and Y passed through the {@link BeetPxUtils.clamp} individually.
*/
clamp(xy1: BpxVector2d, xy2: BpxVector2d): BpxVector2d;
/**
* @returns Creates a vector with X and Y passed through the {@link BeetPxUtils.mod} individually.
* This variant of the method uses X and Y of another vector to run `mod` on both X and Y
* respectively.
*/
mod(other: BpxVector2d): BpxVector2d;
/**
* @returns Creates a vector with X and Y passed through the {@link BeetPxUtils.mod} individually.
* This variant of the method uses a single value to run `mod` on both X and Y
* with it.
*/
mod(value: number): BpxVector2d;
/**
* @returns Creates a vector with X and Y passed through the {@link BeetPxUtils.mod} individually.
* This variant of the method uses X and Y to run `mod` on both X and Y
* respectively.
*/
mod(x: number, y: number): BpxVector2d;
/**
* Addition.
*/
add(other: BpxVector2d): BpxVector2d;
/**
* Addition.
*/
add(value: number): BpxVector2d;
/**
* Addition.
*/
add(x: number, y: number): BpxVector2d;
/**
* Subtraction.
*/
sub(other: BpxVector2d): BpxVector2d;
/**
* Subtraction.
*/
sub(value: number): BpxVector2d;
/**
* Subtraction.
*/
sub(x: number, y: number): BpxVector2d;
/**
* Multiplication.
*/
mul(other: BpxVector2d): BpxVector2d;
/**
* Multiplication.
*/
mul(value: number): BpxVector2d;
/**
* Multiplication.
*/
mul(x: number, y: number): BpxVector2d;
/**
* Division.
*/
div(other: BpxVector2d): BpxVector2d;
/**
* Division.
*/
div(value: number): BpxVector2d;
/**
* Division.
*/
div(x: number, y: number): BpxVector2d;
/**
* This definition allows to "spread" the vector, e.g.: `[...myVector]`.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator
*/
[Symbol.iterator](): Generator<number>;
/**
* This definition serializes the vector to a string `(x,y)` when coercion happens, e.g.: `+myVector`.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive
*/
[Symbol.toPrimitive](hint: "default" | "string" | "number"): string | number;
/**
* This definition makes the vector represented with its class names in those scenario where normally
* you would see `[object Object]` in logs.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag
*/
get [Symbol.toStringTag](): string;
/**
* A convenience method used by the internal logger to print vectors no as JS object,
* but as `(x, y)` strings.
*
* Usually you wouldn't have to call this method directly in your game code.
*
* @see {@link BpxPrintDebug}
* @see {@link BeetPx.logDebug}
* @see {@link BeetPx.logInfo}
* @see {@link BeetPx.logWarn}
* @see {@link BeetPx.logError}
*/
__printDebug(): string;
}
/**
* @see {@link BeetPxDraw.takeCanvasSnapshot}
*
* @see https://github.com/beetrootpaul/beetpx-examples/tree/main/canvas-snapshot
*
* @category Drawing
*/
declare class BpxCanvasSnapshotColorMapping {
#private;
/**
* Creates a simplified color mapping, based on a map of canvas snapshot colors to the new ones.
*
* @example
* ```ts
* BpxCanvasSnapshotColorMapping.from([
* [$rgb_red, $rgb_green],
* [$rgb_blue, $rgb_green],
* [$rgb_yellow, $rgb_red],
* ]);
* ```
*
* @group Static factories
*/
static from(colorMappingEntries: Array<[BpxRgbColor, BpxRgbColor]>): BpxCanvasSnapshotColorMapping;
/**
* Creates a color mapping which uses a function to map a canvas snapshot color
* into a new one.
*
* @example
* ```ts
* BpxCanvasSnapshotColorMapping.of((color: BpxRgbColor | null, spriteX: number, spriteY: number) =>
* color
* ? $rgb(255 - color.r, 255 - color.g, 255 - color.b)
* : null
* );
* ```
*
* @group Static factories
*/
static of(mapper: BpxColorMapper): BpxCanvasSnapshotColorMapping;
/**
* A property helpful for TypeScript type inference, when distinguishing from
* other types of colors.
*
* @example
* ```ts
* const c:
* | null
* | BpxRgbColor
* | BpxPatternColors
* | BpxSpriteColorMapping
* | BpxCanvasSnapshotColorMapping
* = getColor();
* if (c == null) {
* // c is transparent here
* } else if (c.type === "rgb") {
* // c is BpxRgbColor here
* } else if (c.type === "pattern") {
* // c is BpxPatternColors here
* } else if (c.type === "sprite_mapping") {
* // c is BpxSpriteColorMapping here
* } else if (c.type === "canvas_snapshot_mapping") {
* // c is BpxCanvasSnapshotColorMapping here
* } else {
* $u.assertUnreachable(c);
* }
* ```
*/
readonly type = "canvas_snapshot_mapping";
private constructor();
/**
* The main method of this class, used to get a mapped color for a given color on the canvas snapshot.
*/
getMappedColor(snapshot: BpxCanvasSnapshot | null, canvasX: number, canvasY: number): BpxRgbColor | null;
}
/**
* A set of two colors, used in combination with {@link BpxDrawingPattern},
* where given pixels are colored with either the `primary` or the `secondary`.
*
* @category Colors
*/
declare class BpxPatternColors {
/**
* The primary color or a transparency (denoted by `null`).
*/
readonly primary: BpxRgbColor | null;
/**
* The secondary color or a transparency (denoted by `null`).
*/
readonly secondary: BpxRgbColor | null;
/**
* @example
* ```ts
* BpxPatternColors.of($rgb_red, $rgb_blue);
* ```
*
* @group Static factories
*/
static of(primary: BpxRgbColor | null, secondary: BpxRgbColor | null): BpxPatternColors;
/**
* A property helpful for TypeScript type inference, when distinguishing from
* other types of colors.
*
* @example
* ```ts
* const c:
* | null
* | BpxRgbColor
* | BpxPatternColors
* | BpxSpriteColorMapping
* | BpxCanvasSnapshotColorMapping
* = getColor();
* if (c == null) {
* // c is transparent here
* } else if (c.type === "rgb") {
* // c is BpxRgbColor here
* } else if (c.type === "pattern") {
* // c is BpxPatternColors here
* } else if (c.type === "sprite_mapping") {
* // c is BpxSpriteColorMapping here
* } else if (c.type === "canvas_snapshot_mapping") {
* // c is BpxCanvasSnapshotColorMapping here
* } else {
* $u.assertUnreachable(c);
* }
* ```
*/
readonly type = "pattern";
private constructor();
}
/**
* @see {@link BeetPxDraw.setSpriteColorMapping}
*
* @category Drawing
*/
declare class BpxSpriteColorMapping {
#private;
/**
* A mapping used by default, which takes sprite colors as they are,
* without any changes. An equivalent of `BpxSpriteColorMapping.of((c, _x, _y) => c)`.
*
* @group Static values
*/
static noMapping: BpxSpriteColorMapping;
/**
* Creates a simplified color mapping, based on a map of sprite colors to the new ones.
*
* `null` can be used to map a given sprite color into a transparency. It is useful e.g. when
* we have a sprite with a black used as a background, so we can treat all black pixels as
* transparent when drawing.
*
* @example
* ```ts
* BpxSpriteColorMapping.from([
* [$rgb_red, $rgb_green],
* [$rgb_blue, $rgb_green],
* [$rgb_yellow, null],
* ]);
* ```
*
* @group Static factories
*/
static from(colorMappingEntries: Array<[BpxRgbColor, BpxRgbColor | null]>): BpxSpriteColorMapping;
/**
* Creates a color mapping which uses a function to map a sprite color
* into a new one.
*
* @example
* ```ts
* BpxSpriteColorMapping.of((color: BpxRgbColor | null, spriteX: number, spriteY: number) =>
* color
* ? $rgb(255 - color.r, 255 - color.g, 255 - color.b)
* : null
* );
* ```
*
* @group Static factories
*/
static of(mapper: BpxColorMapper): BpxSpriteColorMapping;
/**
* A property helpful for TypeScript type inference, when distinguishing from
* other types of colors.
*
* @example
* ```ts
* const c:
* | null
* | BpxRgbColor
* | BpxPatternColors
* | BpxSpriteColorMapping
* | BpxCanvasSnapshotColorMapping
* = getColor();
* if (c == null) {
* // c is transparent here
* } else if (c.type === "rgb") {
* // c is BpxRgbColor here
* } else if (c.type === "pattern") {
* // c is BpxPatternColors here
* } else if (c.type === "sprite_mapping") {
* // c is BpxSpriteColorMapping here
* } else if (c.type === "canvas_snapshot_mapping") {
* // c is BpxCanvasSnapshotColorMapping here
* } else {
* $u.assertUnreachable(c);
* }
* ```
*/
readonly type = "sprite_mapping";
private constructor();
/**
* The main method of this class, used to get a mapped color for a given color on the sprite.
*/
getMappedColor(spriteColor: BpxRgbColor | null, spriteX: number, spriteY: number): BpxRgbColor | null;
}
/**
* A 1-bit image rectangular image defined in-code.
*
* @category Drawing
*/
declare class BpxPixels {
/**
* @example
* ```ts
* BpxPixels.from(`
* #####
* #-#-#
* #-#-#
* #####
* `);
* ```
*
* @group Static factories
*/
static from(ascii: string): BpxPixels;
/**
* The `#`/`-` representation of the image, split into rows.
*/
readonly asciiRows: string[];
/**
* The size of the image.
*/
readonly size: BpxVector2d;
private constructor();
}
/**
* @see {@link $spr}
*
* @category Drawing
*/
type BpxImageBoundSpriteFactory = (w: number, h: number, x: number, y: number) => BpxSprite;
/**
* A definition of a sprite,
* which can later be used for drawing by {@link BeetPxDraw.sprite}.
*
* @see {@link $spr}
*
* @category Drawing
*/
declare class BpxSprite {
/**
* @see {@link $spr}
*
* @group Static factories
*/
static from(imageUrl: BpxImageUrl, w: number, h: number, x: number, y: number): BpxSprite;
/**
* A property helpful for TypeScript type inference, when distinguishing from
* other types of sprites.
*
* @example
* ```ts
* const s: BpxSprite | BpxAnimatedSprite = getSprite();
* if (s.type === "static") {
* // s is BpxSprite here
* } else if (s.type === "animated") {
* // s is BpxAnimatedSprite here
* } else {
* $u.assertUnreachable(s);
* }
* ```
*/
readonly type = "static";
readonly imageUrl: BpxImageUrl;
readonly size: BpxVector2d;
readonly xy: BpxVector2d;
private constructor();
/**
* Creates a new sprite definition, clipped by given sprite coordinates.
*/
clipBy(xy1: BpxVector2d, xy2: BpxVector2d): BpxSprite;
}
/**
* The map of how much to adjust the vertical placement of this glyph if the
* previous text segment (char) was one of the keys in this map.
*
* @example
* ```ts
* $d.setFont(
* $font({
* glyphs: new Map<string, BpxGlyph>([
* [
* "T",
* {
* // ...
* },
* ],
* [
* "i",
* {
* // ...
* kerning: {
* // put "i" a 1 px closer to "T", so they do not look so distant visually
* T: -1,
* },
* },
* ],
* ]),
* }),
* );
* ```
*
* @category Fonts
*/
type BpxKerningPrevSegmentMap = {
[prevSegment: string]: number;
};
/**
* A map of special text sequences to be treated as instructions to change the color of the
* printed text from a given char position.
*
* @example
* ```ts
* const prevMarkers = $d.setTextColorMarkers({
* red_theBest: $rgb_red,
* b: $rgb_blue,
* });
* $d.text("colors are: green, [b]blue, [red_theBest]red", $v(10), $rgb_green);
* $d.setTextColorMarkers(prevMarkers);
* ```
*
* @see {@link BeetPxDraw.setTextColorMarkers}
*
* @category Drawing
*/
type BpxTextColorMarkers = {
[marker: string]: BpxRgbColor;
};
/**
* A definition of a glyph used by a font. Used as values in {@link BpxFontConfig.glyphs}.
*
* @category Fonts
*/
type BpxGlyph = {
/** A property used in checking which type of a glyph it is, so TypeScript can infer its properties correctly. */
type: "sprite";
/** A sprite to be drawn for this glyph. */
sprite: BpxSprite;
/** A function used to distinguish text from its background on a sprite sheet. */
isTextColor: (color: BpxRgbColor | null) => boolean;
/** How much to move the text drawing cursor to the right after drawing this glyph. Measured from the left edge of the glyph. */
advance: number;
/** The relative position of the glyph to be drawn in relation to the current cursor position. */
offset?: BpxVector2d;
/** The map of how much to adjust the vertical placement of this glyph if the previous text segment (char) was one of the keys in this map. */
kerning?: BpxKerningPrevSegmentMap;
} | {
/** A property used in checking which type of a glyph it is, so TypeScript can infer its properties correctly. */
type: "pixels";
/** A sprite to be drawn for this glyph, represented by 1-bit representation in the game code. */
pixels: BpxPixels;
/** How much to move the text drawing cursor to the right after drawing this glyph. Measured from the left edge of the glyph. */
advance: number;
/** The relative position of the glyph to be drawn in relation to the current cursor position. */
offset?: BpxVector2d;
/** The map of how much to adjust the vertical placement of this glyph if the previous text segment (char) was one of the keys in this map. */
kerning?: BpxKerningPrevSegmentMap;
} | {
/** A property used in checking which type of a glyph it is, so TypeScript can infer its properties correctly. */
type: "whitespace";
/** How much to move the text drawing cursor to the right after processing this glyph. Measured from the left edge of the glyph. */
advance: number;
/** The map of how much to adjust the vertical placement of this glyph if the previous text segment (char) was one of the keys in this map. */
kerning?: BpxKerningPrevSegmentMap;
};
/**
* Similar to {@link BpxGlyph}, but after being arranged by {@link BpxFont.arrangeGlyphsFor}
* in context of given glyphs' placement, text color, and color markers.
*
* Used by {@link BeetPxDraw.measureText} for a headless text rendering. Also, used
* by {@link BeetPxDraw.text} for an actual text rendering.
*
* @category Fonts
*/
type BpxArrangedGlyph = {
type: "sprite";
char: string;
/** Left-top position of a glyph in relation to the left-top of the entire text. */
leftTop: BpxVector2d;
/** Line number within the entire text (multiple lines can be achieved by including `\n` within the text). */
lineNumber: number;
sprite: BpxSprite;
/** The color mapping used to draw a glyph's sprite in a desired text color. */
spriteColorMapping: BpxSpriteColorMapping;
} | {
type: "pixels";
char: string;
/** Left-top position of a glyph in relation to the left-top of the entire text. */
leftTop: BpxVector2d;
/** Line number within the entire text (multiple lines can be achieved by including `\n` within the text). */
lineNumber: number;
pixels: BpxPixels;
color: BpxRgbColor;
} | {
type: "line_break";
/** Line number within the entire text (multiple lines can be achieved by including `\n` within the text). */
lineNumber: number;
};
/**
* A font definition.
*
* @example
* ```ts
* $d.setFont($font({
* ascent: 5,
* descent: 0,
* lineGap: 1,
*
* mapGrapheme(grapheme: string): string {
* return grapheme.toLowerCase();
* },
*
* glyphs: new Map<string, BpxGlyph>([
* [" ", { type: "whitespace", advance: 4 }],
* ["0", { type: "sprite", ... }],
* // a lot more glyphs defined here
* ]),
* });
* ```
*
* @see https://github.com/beetrootpaul/beetpx-examples/tree/main/fonts
*
* @category Fonts
*/
type BpxFontConfig = {
/**
* An amount of pixels from the baseline (included) to the top-most pixel of font's glyphs.
*/
ascent: number;
/**
* An amount of pixels from the baseline (excluded) to the bottom-most pixel of font's glyphs.
*/
descent: number;
/**
* An amount of pixels between the bottom-most pixel of the previous line (excluded) and
* the top-most pixel of the next line (excluded).
*/
lineGap: number;
/**
* This functions maps the text grapheme (a user-perceived character like `a` or a
* multi-character emoji like `❤️`) before trying to find its corresponding glyph
* in a `glyphs` map. It would be typically used to call `grapheme.toLowerCase()`
* in fonts which have glyphs defined for lower-case characters only.
*/
mapGrapheme: (grapheme: string) => string;
/**
* A map which contains the glyphs for specified graphemes (keys of the map).
* Grapheme is a user-perceived character like `a` or a multi-character emoji
* like `❤️`. Before retrieving a glyph from this map, a grapheme is normalized
* with use of `mapGrapheme` function. Typically, it would be useful when you
* want to specify same glyphs for both upper-case and lower-case characters,
* so you are able to define lower-case ones only and then implement
* `mapGrapheme` as `grapheme.toLowerCase()`.
*/
glyphs: Map<string, BpxGlyph>;
};
/**
* An instance of a font, defined with use of {@link BpxFontConfig}.
*
* @see https://github.com/beetrootpaul/beetpx-examples/tree/main/fonts
*
* @category Fonts
*/
declare class BpxFont {
#private;
/**
* A method to create a font from scratch.
*
* @group Static factories
*/
static of(config: Partial<BpxFontConfig>): BpxFont;
/**
* A method to create a font as an extension of an already defined font.
*
* @example
* ```ts
* const pico8FontWithExtraGlyphs = BpxFont.basedOn($font_pico8, baseFontConfig => ({
* ...baseFontConfig,
* glyphs: new Map<string, BpxGlyph>([
* ...baseFontConfig.glyphs,
* // additional glyphs defined here
* ]),
* });
* ```
*
* @group Static factories
*/
static basedOn(baseFont: BpxFont, extendedConfig: (baseFontConfig: BpxFontConfig) => BpxFontConfig): BpxFont;
private constructor();
/**
* A list of sprite sheets gathered from the all sprite glyphs defined for this font.
*
* Useful for defining the assets to fetch in {@link BeetPx.start}
*
* @example
* ```ts
* $x.start({
* // ...
* assets: [
* ...myFont.spriteSheetUrls
* ],
* })
* ```
*/
get spriteSheetUrls(): string[];
/**
* @see {@link BpxFontConfig.ascent}
*/
get ascent(): number;
/**
* @see {@link BpxFontConfig.descent}
*/
get descent(): number;
/**
* @see {@link BpxFontConfig.lineGap}
*/
get lineGap(): number;
/**
* The main methods of the font, which iterates of the text segments (characters, but with a support
* for multi-char emojis, e.g. "❤️"), and arranges their corresponding glyphs in a virtual visual space.
*
* The resulting array of {@link BpxArrangedGlyph} is further used by {@link BeetPxDraw.measureText}
* for a headless text rendering and by {@link BeetPxDraw.text} for an actual text rendering.
*
* You rather doesn't have to use this method directly.
*/
arrangeGlyphsFor(text: string, textColor: BpxRgbColor, colorMarkers?: BpxTextColorMarkers): BpxArrangedGlyph[];
}
/**
* @see {@link $aspr}
*
* @category Drawing
*/
type BpxImageBoundAnimatedSpriteFactory = (w: number, h: number, xys: [x: number, y: number][], opts?: {
frameDuration?: number;
paused?: boolean;
onGamePause?: "pause" | "ignore";
}) => BpxAnimatedSprite;
/**
* A definition of an animated sprite,
* which can later be used (indirectly) for drawing by {@link BeetPxDraw.sprite}.
*
* It has a form of a collection sprites, originated from the
* same sprite sheet.
*
* @example
* ```ts
* let myAnimation: BpxAnimatedSprite;
*
* $x.setOnStarted(() => {
* myAnimation = $aspr("spritesheet.png")(8, 8, [
* [0,0],
* [8,0],
* [16,0],
* ]);
* });
*
* $d.setOnDraw(() => {
* $d.sprite(myAnimation.current, $v(10));
* });
* ```
*
* @remarks
* Under the hood this class uses {@link BpxTimer} to integrate
* the animation progression with the game loop.
*
* @see {@link $aspr}
*
* @category Drawing
*/
declare class BpxAnimatedSprite {
#private;
/**
* @see {@link $aspr}
*
* @group Static factories
*/
static from(imageUrl: BpxImageUrl, w: number, h: number, xys: [x: number, y: number][], opts?: {
frameDuration?: number;
paused?: boolean;
onGamePause?: "pause" | "ignore";
}): BpxAnimatedSprite;
/**
* A property helpful for TypeScript type inference, when distinguishing from
* other types of sprites.
*
* @example
* ```ts
* const s: BpxSprite | BpxAnimatedSprite = getSprite();
* if (s.type === "static") {
* // s is BpxSprite here
* } else if (s.type === "animated") {
* // s is BpxAnimatedSprite here
* } else {
* $u.assertUnreachable(s);
* }
* ```
*/
readonly type = "animated";
readonly imageUrl: BpxImageUrl;
readonly size: BpxVector2d;
private constructor();
/**
* A sprite to be drawn in the current game loop iteration.
*/
get current(): BpxSprite;
/**
* An index of the sprite from the list of sprites of this animation.
*/
get t(): number;
/**
* Whether the animation is paused.
*/
get isPaused(): boolean;
/**
* Pauses the animation.
*/
pause(): void;
/**
* Resumes the animation.
*/
resume(): void;
/**
* Restarts the animation from its first frame.
*/
restart(): void;
}
/**
* A 4x4 drawing pattern definition of which pixels should be drawn with the `primary`
* and which with the `secondary` of {@link BpxPatternColors}.
*
* @example
* ```ts
* const prevPattern = $d.setDrawingPattern(BpxDrawingPattern.from(`
* ##--
* ##--
* --##
* --##
* `));
* $d.rectFilled($v(10), $v(20), BpxPatternColors.of($rgb_red, $rgb_blue));
* $d.setDrawingPattern(prevPattern);
* ```
*
* @category Drawing
*/
declare class BpxDrawingPattern {
#private;
/**
* Creates a BpxDrawingPattern from a visual representation of 4 columns and 4 rows
* (designated by new lines) where `#` and `-` stand for a primary and
* a secondary color. Whitespaces are ignored.
*
* @category Static factories
*/
static from(ascii: string): BpxDrawingPattern;
/**
* Creates a BpxDrawingPattern from a numeric representation of 4 columns and 4 rows.
* Recommended way is to defined the pattern as a binary number, with group separator
* put between each 4 digits, e.g. `0b0101_1010_0101_1010`. The `1` stands for the primary
* color and the `0` – for the secondary one.
*
* @category Static factories
*/
static of(bits: number): BpxDrawingPattern;
/**
* The pattern used by default, which uses the primary color only.
* An equivalent of `BpxDrawingPattern.of(0b1111_1111_1111_1111)`.
*
* @category Static values
*/
static primaryOnly: BpxDrawingPattern;
/**
* The pattern which uses the secondary color only.
* An equivalent of `BpxDrawingPattern.of(0b0000_0000_0000_0000)`.
*
* @category Static values
*/
static secondaryOnly: BpxDrawingPattern;
private constructor();
/**
* The method to check whether a primary or a secondary color should be put at a given (X,Y)
* when this pattern is applied.
*
* Usually, you wouldn't have to use this method, since it's already used by internals of
* BeetPx drawing API.
*/
hasPrimaryColorAt(x: number, y: number): boolean;
}
/**
* Text measurement calculated by a headless text rendering with use of
* {@link BeetPxDraw.measureText}.
*
* @category Drawing
*/
type BpxTextMeasurement = {
/** The size of the drawn text. */
wh: BpxVector2d;
/** The offset of the text placement in relation to where it was intended to be placed. Useful when the text is meant to be drawn centered, so it starts half of its width/height to the left/up from the given point. */
offset: BpxVector2d;
};
/**
* @see {@link BpxFrameworkConfig}'s `debugMode.fpsDisplay.placement`
*
* @category Debug
*/
type BpxFpsDisplayPlacement = "top-left" | "top-right" | "bottom-left" | "bottom-right";
/**
* Identifiers of the game buttons.
*
* @example
* ```ts
* $x.wasButtonJustPressed("X");
* ```
*
* @remarks
* - `O` represents the Japanese "Maru" sign, kind of a "Yes". Good for a primary/accept/next button.
* - `X` represents the Japanese "Batsu" sign, kind of a "No". Good for a secondary/cancel/back button.
* - Lower case `o` and `x` are supported as well, for a convenience.
*
* @category Game input
*/
type BpxGameButtonName = "left" | "right" | "up" | "down" | "O" | "o" | "X" | "x" | "menu";
/**
* @see {@link BeetPx.getConnectedGamepadTypes}
*
* @category Game input
*/
type BpxGamepadType = "xbox" | "dualsense" | "8bitdo" | "other";
/**
* @see {@link BeetPx.getRecentInputMethods}
*
* @category Game input
*/
type BpxGameInputMethod = "gamepad" | "keyboard" | "mouse" | "touch";
/**
* Identifiers of the game input events.
*
* Typically you wouldn't need to use those type values unless dealing
* with custom even handling.
*
* @see {@link BeetPx.getEventsCapturedInLastUpdate}
*
* @category Game input
*/
type BpxGameInputEvent = null | "button_left" | "button_right" | "button_up" | "button_down" | "button_O" | "button_X" | "button_menu" | "mute_unmute_toggle" | "full_screen" | "take_screenshot" | "browse_screenshots_toggle" | "debug_toggle" | "frame_by_frame_toggle" | "frame_by_frame_step";
declare global {
interface Document {
webkitFullscreenEnabled?: boolean;
webkitFullscreenElement?: () => Element;
webkitExitFullscreen?: () => void;
}
interface Element {
webkitRequestFullscreen?: () => void;
}
}
/**
* A simple JSON-like type constraint for values that can be persisted with use of
* {@link BeetPx.savePersistedState}.
*
* @category Storage
*/
type BpxPersistedStateValueConstraints = Record<string, string | number | boolean | null | undefined>;
/**
* The configuration of the BeetPx framework. Passed into {@link BeetPx.start}.
*
* @category Core
*/
type BpxFrameworkConfig = {
/**
* Used for scoping localStorage keys, so two different games won't override their persisted state.
*
* An example: built-in screenshots feature binds screenshots to the proper game by its `gameId`.
*/
gameId: string;
/**
* The logical canvas size. Not to be mistaken with a size of the HTML Canvas, which the user has no control over.
*
* During the game, this value (as a {@link BpxVector2d} can be obtained with {@link BeetPx.canvasSize}.
*/
canvasSize?: "64x64" | "128x128" | "256x256";
/**
* The desired frequency of update calls. This is a basis for all time-based computations
* in the game, since BeetPx has no notion of the real time, nor delta time between update calls.
* The entire framework is based in a fixed timestep computations, where you can expect each game loop
* iteration to happen after the similar amount of time from the previous one.
*
* 60 FPS games looks smoother, but require more performant machine, if the game logic is
* computation heavy.
*
* PleaseThis setting does *not* imply the rendering FPS, which is decoupled from the update calls.
*/
fixedTimestep?: "30fps" | "60fps";
/**
* A list of URLs of assets to load. The URLs might be either relative to the `./public/` directory,
* or external ones.
*
* Allowed file extensions:
* - `.png` – for images,
* - `.wav` – for music,
* - `.flac` – for music, smaller files than `.wav`,
* - `.json` – for JSON files,
* - `.ldtk` – a convenience extension support for JSON files with the default extension used by [LDtk](https://ldtk.io/) tool, so you doesn't have to rename them.
*
* @example
* ```ts
* $x.start({
* // ...
* assets: [
* "spriteshet.png", // refers to `./public/spriteshet.png`
* "music/track1.flac", // refers to `./public/music/track1.flac`
* "https://the.url/of/level.ldtk",
* ],
* });
* ```
*/
assets?: BpxAssetsToLoad;
/**
* A feature which allows to toggle a game pause with use of a "menu" button.
* When active, the timers, animations, and music do not progress, unless configured to ignore the pause.
*
* This also allows to implement a pause menu.
*
* @example
* ```ts
* $x.setOnDraw(() => {
* // ...
* if ($x.isPaused) {
* pauseMenu.draw();
* }
* });
* ```
*
* @see https://github.com/beetrootpaul/beetpx-examples/tree/main/pause-and-restart
*/
gamePause?: {
/**
* Whether the game pause should be available (and automatically toggled with the "menu" button).
*/
available?: boolean;
};
/**
* Whether to prevent user from accidentally closing the browser tab with the game running.
*
* A recommended approach would be to set it to {@link BEETPX__IS_PROD}
*
* @example
* ```ts
* $x.start({
* // ...,
* requireConfirmationOnTabClose: BEETPX__IS_PROD,
* });
* ```
*/
requireConfirmationOnTabClose?: boolean;
screenshots?: {
/**
* Whether to allow user to take screenshots of the game (with use of the `]` key)
* and access the screenshot browser overlay (with use of the `}` key).
*/
available?: boolean;
};
/**
* A mode in which you can perform an additional logic, draw helpful markers, etc.
* When active, the {@link BeetPx.debug} returns `true`.
*
* Visually, this mode is indicated by an orange border around the game canvas.
*
* When inactive, the {@link BeetPx.logDebug} are not printed.
*
* @example
* ```ts
* $d.sprite(playerSprite, xy);
* if ($x.debug) {
* $d.rect(xy, playerSprite.size, $rgb_red);
* }
* ```
*/
debugMode?: {
/**
* Whether to allow use to toggle the debug mode (with use of the `;` key).
*
* A recommended approach would be to set it to the negation of {@link BEETPX__IS_PROD}.
*/
available?: boolean;
/**
* Whether to activate the debug mode from the game start. Useful, when you
* want to investigate what happens on the very first frame. This setting ignores
* the persisted state of whether the debug mode was activated the last time the games was run.
*/
forceEnabledOnStart?: boolean;
/**
* FPS Display shows the rendering FPS in one of the canvas corners, when in enabled and in the debug mode.
*/
fpsDisplay?: {
/**
* Whether the FPS Display should be shown in the debug mode.
*/
enabled?: boolean;
/**
* The color of the printed FPS on the canvas.
*/
color?: BpxRgbColor;
/**
* The placement of the printed FPS on the canvas.
*/
placement?: BpxFpsDisplayPlacement;
};
};
frameByFrame?: {
/**
* Whether to allow use to toggle the frame-by-frame mode (with use of the `,` key),
* and (when in that mode) to progress to the next frame (with use of the `.` key).
*
* A recommended approach would be to set it to the negation of {@link BEETPX__IS_PROD}.
*/
available?: boolean;
/**
* Whether to activate the frame-by-frame mode from the game start. Useful, when you
* want to investigate what happens on the very first frame.
*/
activateOnStart?: boolean;
};
};
/**
* @category Miscellaneous
*/
type BpxEasingFn = (t: number) => number;
/**
* A collection of easing functions. Based on
* ["Animation Curves cheat sheet/library" PICO-8 cart by ValerADHD](https://www.lexaloffle.com/bbs/?tid=40577).
*
* @category Miscellaneous
*/
declare class BpxEasing {
private constructor();
/**
* @group Static values
*/
static linear: BpxEasingFn;
/**
* @group Static values
*/
static inQuadratic: BpxEasingFn;
/**
* @group Static values
*/
static outQuadratic: BpxEasingFn;
/**
* @group Static values
*/
static inOutQuadratic: BpxEasingFn;
/**
* @group Static values
*/
static outInQuadratic: BpxEasingFn;
/**
* @group Static values
*/
static inQuartic: BpxEasingFn;
/**
* @group Static values
*/
static outQuartic: BpxEasingFn;
/**
* @group Static values
*/
static inOutQuartic: BpxEasingFn;
/**
* @group Static values
*/
static outInQuartic: BpxEasingFn;
/**
* @group Static values
*/
static inOvershoot: BpxEasingFn;
/**
* @group Static values
*/
static outOvershoot: BpxEasingFn;
/**
* @group Static values
*/
static inOutOvershoot: BpxEasingFn;
/**
* @group Static values
*/
static outInOvershoot: BpxEasingFn;
/**
* @group Static values
*/
static inElastic: BpxEasingFn;
/**
* @group Static values
*/
static outElastic: BpxEasingFn;
/**
* @group Static values
*/
static inOutElastic: BpxEasingFn;
/**
* @group Static values
*/
static outInElastic: BpxEasingFn;
/**
* @group Static values
*/
static inBounce: BpxEasingFn;
/**
* @group Static values
*/
static outBounce: BpxEasingFn;
}
/**
* A free to use (CC-0) color palette created by zep and distributed as part of PICO-8 fantasy console.
*
* Links:
* - https://www.lexaloffle.com/pico-8.php?page=faq – an info about the palette being available under a CC-0 license
* - https://pico-8.fandom.com/wiki/Palette#The_system_palette – hex values are copy-pasted from there
*
* @category Colors
*/
declare class BpxPalettePico8 {
private constructor();
/**
* Color `#000000`.
*
* @group Static values
*/
static black: BpxRgbColor;
/**
* Color `#1D2B53`.
*
* @group Static values
*/
static storm: BpxRgbColor;
/**
* Color `#7E2553`.
*
* @group Static values
*/
static wine: BpxRgbColor;
/**
* Color `#008751`.
*
* @group Static values
*/
static moss: BpxRgbColor;
/**
* Color `#AB5236`.
*
* @group Static values
*/
static tan: BpxRgbColor;
/**
* Color `#5F574F`.
*
* @group Static values
*/
static slate: BpxRgbColor;
/**
* Color `#C2C3C7`.
*
* @group Stati