breakout71/src/types.d.ts

282 lines
7 KiB
TypeScript
Raw Normal View History

2025-03-19 20:14:55 +01:00
import { rawUpgrades } from "./upgrades";
2025-03-16 17:45:29 +01:00
import { options } from "./options";
export type colorString = string;
2025-03-06 14:06:02 +01:00
export type RawLevel = {
name: string;
size: number;
bricks: string;
svg: number | null;
color: string;
2025-03-06 14:06:02 +01:00
};
export type Level = {
name: string;
size: number;
bricks: colorString[];
svg: string;
color: string;
threshold: number;
sortKey: number;
2025-03-06 14:06:02 +01:00
};
export type Palette = { [k: string]: string };
2025-03-06 14:06:02 +01:00
export type Upgrade = {
threshold: number;
giftable: boolean;
id: PerkId;
name: string;
icon: string;
max: number;
help: (lvl: number) => string;
fullHelp: string;
requires: PerkId | "";
};
2025-03-06 14:06:02 +01:00
export type PerkId = (typeof rawUpgrades)[number]["id"];
2025-03-06 14:06:02 +01:00
declare global {
interface Window {
webkitAudioContext?: typeof AudioContext;
}
interface Document {
webkitFullscreenEnabled?: boolean;
webkitCancelFullScreen?: () => void;
}
interface Element {
webkitRequestFullscreen: typeof Element.requestFullscreen;
}
interface MediaStream {
// https://devdoc.net/web/developer.mozilla.org/en-US/docs/Web/API/CanvasCaptureMediaStream.html
// On firefox, the capture stream has the requestFrame option
// instead of the track, go figure
requestFrame?: () => void;
}
2025-03-07 11:34:11 +01:00
}
export type BallLike = {
x: number;
y: number;
vx?: number;
vy?: number;
2025-03-07 20:18:18 +01:00
};
2025-03-07 11:34:11 +01:00
export type Coin = {
points: number;
color: colorString;
x: number;
y: number;
size: number;
previousX: number;
previousY: number;
vx: number;
vy: number;
sx: number;
sy: number;
a: number;
sa: number;
weight: number;
destroyed?: boolean;
coloredABrick?: boolean;
2025-03-07 20:18:18 +01:00
};
export type Ball = {
x: number;
previousX: number;
y: number;
previousY: number;
vx: number;
vy: number;
previousVX: number;
previousVY: number;
sx: number;
sy: number;
2025-03-22 16:04:25 +01:00
// Uses of the pierce perk only
piercedSinceBounce: number;
2025-03-22 16:04:25 +01:00
// Any bounce counts, even if brick resisted the hit
hitSinceBounce: number;
2025-03-22 16:04:25 +01:00
// Brick was really broken ,but could have been respawned as a bomb
brokenSinceBounce: number;
// Bricks that have been destroyed (and not replaced by something else)
hitItem: { index: number; color: string }[];
sapperUses: number;
destroyed?: boolean;
2025-03-07 20:18:18 +01:00
};
interface BaseFlash {
time: number;
color: colorString;
duration: number;
size: number;
destroyed?: boolean;
x: number;
y: number;
}
2025-03-14 11:59:49 +01:00
2025-03-11 13:56:42 +01:00
interface ParticleFlash extends BaseFlash {
2025-03-18 14:16:12 +01:00
// type: "particle";
vx: number;
vy: number;
ethereal: boolean;
}
2025-03-11 13:56:42 +01:00
interface TextFlash extends BaseFlash {
2025-03-18 14:16:12 +01:00
// type: "text";
text: string;
}
2025-03-18 14:16:12 +01:00
interface LightFlash extends BaseFlash {
// type: "ball";
}
2025-03-18 14:16:12 +01:00
export type Flash = ParticleFlash | TextFlash | LightFlash;
2025-03-07 20:18:18 +01:00
export type RunStats = {
started: number;
levelsPlayed: number;
runTime: number;
coins_spawned: number;
score: number;
bricks_broken: number;
misses: number;
balls_lost: number;
puck_bounces: number;
2025-03-16 17:45:29 +01:00
wall_bounces: number;
upgrades_picked: number;
max_combo: number;
max_level: number;
2025-03-07 20:18:18 +01:00
};
export type PerksMap = {
[k in PerkId]: number;
};
2025-03-18 08:19:20 +01:00
export type ReusableArray<T> = {
// All items below that index should not be destroyed
2025-03-18 14:16:12 +01:00
indexMin: number;
total: number;
list: T[];
};
2025-03-18 08:19:20 +01:00
2025-03-07 20:18:18 +01:00
export type RunHistoryItem = RunStats & {
perks?: PerksMap;
appVersion?: string;
};
export type GameState = {
// Width of the canvas element in pixels
canvasWidth: number;
// Height of the canvas element in pixels
canvasHeight: number;
// Distance between the left of the canvas and the left of the leftmost brick, in pixels
offsetX: number;
// Distance between the left of the canvas and the left border of the game area, in pixels.
// Can be 0 when no border is shown
offsetXRoundedDown: number;
// Width of the bricks area, in pixels
gameZoneWidth: number;
// Width of the game area between the left and right borders, in pixels
gameZoneWidthRoundedUp: number;
// Height of the play area, between the top of the canvas and the bottom of the puck.
// Does not include the finger zone on mobile.
gameZoneHeight: number;
// Size of one brick in pixels
brickWidth: number;
// Size of the current level's grid
gridSize: number;
// 0 based index of the current level in the run (level X / 7)
currentLevel: number;
2025-03-20 23:11:42 +01:00
upgradesOfferedFor: number;
// 10 levels selected randomly at start for the run
runLevels: Level[];
// Width of the puck in pixels, changed by some perks and resizes
puckWidth: number;
// perks the user currently has
perks: PerksMap;
// Base speed of the ball in pixels/tick
baseSpeed: number;
// Score multiplier
combo: number;
// Whether the game is running or paused
running: boolean;
2025-03-22 16:04:25 +01:00
isGameOver: boolean;
2025-03-18 14:16:12 +01:00
ballStickToPuck: boolean;
2025-03-16 20:11:08 +01:00
// Whether the game should be re-rendered once even if not running
needsRender: boolean;
// Position of the center of the puck on the canvas in pixels, from the left of the canvas.
puckPosition: number;
// Will be set if the game is about to be paused. Game pause is delayed by a few milliseconds if you pause a few times in a run,
// to avoid abuse of the "release to pause" feature on mobile.
pauseTimeout: NodeJS.Timeout | null;
// Current run score
score: number;
// levelTime of the last time the score increase, to render the score differently
lastScoreIncrease: number;
// levelTime of the last explosion, for screen shake
lastExplosion: number;
// High score at the beginning of the run
highScore: number;
// Balls currently in game, game over if it's empty
balls: Ball[];
// Color of the balls, can be changed by some perks
ballsColor: colorString;
// Array of bricks to display. 'black' means bomb. '' means no brick.
bricks: colorString[];
// Number of times a brick has been hit already
brickHP: number[];
2025-03-18 14:16:12 +01:00
particles: ReusableArray<ParticleFlash>;
texts: ReusableArray<TextFlash>;
lights: ReusableArray<LightFlash>;
2025-03-18 08:19:20 +01:00
coins: ReusableArray<Coin>;
levelStartScore: number;
levelMisses: number;
levelSpawnedCoins: number;
lastPlayedCoinGrab: number;
// MAX_COINS: number;
// MAX_PARTICLES: number;
puckColor: colorString;
ballSize: number;
coinSize: number;
puckHeight: number;
totalScoreAtRunStart: number;
isCreativeModeRun: boolean;
pauseUsesDuringRun: number;
keyboardPuckSpeed: number;
lastTick: number;
lastTickDown: number;
runStatistics: RunStats;
lastOffered: Partial<{ [k in PerkId]: number }>;
levelTime: number;
2025-03-22 16:47:02 +01:00
winAt: number;
2025-03-16 17:45:29 +01:00
levelWallBounces: number;
autoCleanUses: number;
2025-03-18 14:16:12 +01:00
aboutToPlaySound: {
wallBeep: { vol: number; x: number };
comboIncreaseMaybe: { vol: number; x: number };
comboDecrease: { vol: number; x: number };
coinBounce: { vol: number; x: number };
explode: { vol: number; x: number };
lifeLost: { vol: number; x: number };
coinCatch: { vol: number; x: number };
colorChange: { vol: number; x: number };
};
2025-03-07 20:18:18 +01:00
};
2025-03-14 11:59:49 +01:00
2025-03-14 12:23:19 +01:00
export type RunParams = {
level?: string;
levelToAvoid?: string;
perks?: Partial<PerksMap>;
};
export type OptionDef = {
default: boolean;
name: string;
help: string;
};
2025-03-16 17:45:29 +01:00
export type OptionId = keyof typeof options;