Skip to content

Latest commit

 

History

History
817 lines (672 loc) · 29.8 KB

File metadata and controls

817 lines (672 loc) · 29.8 KB

📘 Arcade Engine API

This reference maps the public exports from arcade-engine to what they do, where to see them, and the simplest way to start using them.

Install the package from npm:

npm install arcade-engine

Import from the package root:

import { GameArena, Ticker, helpers } from "arcade-engine";

Minimal loop:

Give #game a CSS width and height before constructing GameArena.

import { GameArena, Ticker, createInputController } from "arcade-engine";

const arena = new GameArena(document.querySelector("#game") as HTMLElement);
const input = createInputController({
  fire: ["Space", "MouseLeft", "TouchPrimary", "Gamepad0"],
  moveLeft: ["ArrowLeft", "KeyA", "GamepadAxisLeftXNegative"],
});
const ticker = new Ticker({ fixedStepFps: 60 });

input.start();

ticker.addSchedule(() => {
  input.updateGamepads();
  arena.clear();
  arena.drawCircle(input.isPressed("moveLeft") ? -24 : 24, 0, 12, {
    backgroundColor: input.isPressed("fire") ? "#f2b84b" : "#4fd1c5",
  });
}, 1);

ticker.start();

Use the package root for browser game code. Use arcade-engine/high-scores from backend routes when you only need score validation and receipt helpers.

🎬 Core Classes

Export What It Does See Also
GameArena Creates and manages a browser canvas, drawing context, fullscreen behavior, asset preloading, text, sprites, circles, and debug grids. Engine/Core/GameArena Storybook section
Ticker Runs animation callbacks on requestAnimationFrame, with optional render FPS caps and fixed-step simulation. Engine/Core/Ticker Storybook section
Sound Wraps browser audio with channels, global controls, fades, playback-blocked reporting, and optional spatial audio. Engine/Audio/Sound Storybook section
helpers Default object containing classic geometry, collision, spawn, rotation, clone, random-color, and event helpers. Engine/Helpers/* Storybook sections
FpsOverlay Draws a Canvas 2D FPS and frame-time overlay with optional target-relative graph coloring. Engine/Core/GameArena/FpsDebugOverlay Storybook story
PerformanceSampler Records frame timings and rolling FPS metrics for custom debug panels. Engine/Core/GameArena/FpsDebugOverlay Storybook story
const arena = new GameArena(document.querySelector("#game") as HTMLElement);
const ticker = new Ticker({ fixedStepFps: 50 });

ticker.addSchedule(() => {
  arena.clear();
  arena.renderText("READY", 0, 0, { align: "center" });
});

ticker.start();

🧭 Debug Overlay

Export Use It For
FpsOverlay Rendering minimal, basic, detailed, or graph FPS overlays to a canvas context.
PerformanceSampler Sampling frame deltas and producing current, average, low, high, and history metrics.
const arena = new GameArena(host, {
  debug: {
    fps: {
      enabled: true,
      level: "graph",
      targetFps: 60,
    },
  },
});

arena.renderDebugOverlay(deltaMs);

🧮 Geometry And Events

These functions are available through the default helpers export.

Helper Use It For
helpers.float(number) Tidying decimal precision.
helpers.findHeading(target, origin?) Distance and heading between two radial objects.
helpers.rotateTo(destinationAngle, currentAngle, stepSize) Gradual steering toward a destination angle.
helpers.getSpawnCoords(target, options?) Enemy, pickup, projectile, or effect spawn positions around a target.
helpers.detectCollision(target, origin?) Radial collision between two objects.
helpers.detectAreaExit(radialCenter, target, radius) Boundary exit checks for circular arenas.
helpers.bind(eventNames, callback, element?) Lightweight DOM event binding.
helpers.unbind(...eventNames) Event cleanup for helpers-bound listeners.
helpers.getRandomColor() Debug or placeholder colors.
helpers.cloneObject(oldObject) Copying plain data objects.
const heading = helpers.findHeading(enemy, player);
enemy.heading = helpers.rotateTo(heading.angle, enemy.heading, 3);

🗺️ String Tile Maps

Use these helpers to author grid maps as text, then query cells by row/column or centered world coordinates.

Export Use It For
parseStringTileMap Parse a multiline string into padded tile rows, with optional tile normalization.
findStringTileMapCell Find the first cell containing a tile symbol.
findStringTileMapCells Find all cells containing a tile symbol.
getStringTileMapTile Read one tile by column and row.
getStringTileMapCenteredPoint Convert a column/row into centered x/z coordinates.
getStringTileMapCellFromCenteredPoint Convert centered x/z coordinates back into a cell.
const map = parseStringTileMap(
  `
########D########
#      S        #
#   P      o    #
#################
`.trim()
);
const spawn = findStringTileMapCell(map, "S");

The isometric dungeon demo uses this editable legend on top of the generic string map parser:

Symbol Meaning Role
space Floor Walkable floor
# Stone wall Blocking wall
. Floor marker Walkable floor marker
C Chest Interactable prop
D Door Interactable doorway
P Pillar Blocking prop
S Player spawn Spawn point
d Stairs down Interactable stairs
o Light source Light
r Rubble Blocking prop
u Stairs up Interactable stairs
w Water Walkable slow floor

Ragged rows can be padded with an internal empty tile such as _; the dungeon demo treats that as void space outside the playable floor and hides it from the editor legend.

🎮 Input Actions

Export Use It For
getInputCode Normalize keyboard, mouse, pointer, touch, gamepad, or string input into an input code.
getInputActions Resolve an input event or input code to semantic actions.
getInputActionState Convert currently pressed inputs into an action-state object.
getGamepadInputCodes Read pressed gamepad buttons and active axes.
createInputController Track keyboard, mouse, touch, pointer, and gamepad inputs through start/stop lifecycle helpers.
createKeyboardInputController Backwards-compatible alias for createInputController.
const input = createInputController({
  fire: ["Space", "MouseLeft", "TouchPrimary", "Gamepad0"],
  moveLeft: ["ArrowLeft", "KeyA", "GamepadAxisLeftXNegative"],
});

input.start();
input.updateGamepads();

if (input.isPressed("fire")) {
  // Fire a shot.
}

👥 Multiplayer Input

Export Use It For
createLocalMultiplayerController Track separate action state for multiple local players.
createMultiplayerSession Describe a local or remote co-op/PvP session without choosing a backend.
createPlayerInputIntent Create serializable player input messages for remote sync.
getPlayerActionState Resolve one player's bindings against pressed inputs.
mergePlayerInputIntent Merge a local or remote player intent into a player-state map.
const multiplayer = createLocalMultiplayerController([
  {
    bindings: { fire: ["Space", "Gamepad0"], moveLeft: ["KeyA"] },
    gamepadIndex: 0,
    id: "p1",
  },
  {
    bindings: { fire: ["Enter", "Gamepad0"], moveLeft: ["KeyJ"] },
    gamepadIndex: 1,
    id: "p2",
  },
]);

multiplayer.start();
multiplayer.updateGamepads();

const state = multiplayer.getState();

Remote multiplayer is supported as data contracts rather than a bundled network stack. Games can send PlayerInputIntent objects through WebSocket, WebRTC, a hosted relay, or their own backend.

📱 Browser Capabilities

Export Use It For
canUseScreenWakeLock Detect whether the browser exposes the Screen Wake Lock API.
ScreenWakeLockController Acquire, release, and reacquire best-effort screen wake locks around gameplay state.
canUseFullscreen Detect fullscreen request support on an element.
canLockOrientation Detect Screen Orientation lock support.
enterImmersiveMode Request fullscreen and an optional orientation lock from a trusted user gesture.
exitInstalledApp Attempt to close an installed app window and dispatch a fallback event if blocked.
appExitBlockedEventName Default event name used by exitInstalledApp.
const wakeLock = new ScreenWakeLockController();

wakeLock.setActive(true);

await enterImmersiveMode({ orientation: "landscape" });

window.addEventListener(appExitBlockedEventName, () => {
  showExitFallback();
});
exitInstalledApp();

These helpers treat browser capability calls as optional. Denied or unsupported requests should not interrupt gameplay.

⚙️ User Options

Export Use It For
createUserOptionsStore Create a typed local options store with defaults, normalization, persistence, reset, subscribers, and optional DOM change events.
normalizeUserOptions Shallow-merge unknown stored values over defaults before app-specific validation.
userOptionsChangedEventName Default DOM event name dispatched after option changes.
const options = createUserOptionsStore({
  defaults: {
    fullscreen: false,
    inputMode: "keyboard",
    volume: 6,
  },
  normalize: (stored, defaults) => ({
    ...normalizeUserOptions(stored, defaults),
    volume: Math.max(0, Math.min(10, Number((stored as { volume?: unknown }).volume ?? defaults.volume))),
  }),
  storageKey: "myGame.options",
  version: 1,
});

options.setOption("volume", 8);
options.subscribe(({ changedKeys, options }) => {
  console.info("Options changed", changedKeys, options);
});

Games own their concrete schema and validation rules. The store owns the browser-safe mechanics of reading, writing, resetting, and notifying.

🧰 Runtime Utilities

Export Use It For
runtimeLogLevels Ordered log-level values for settings menus.
isRuntimeLogLevel Type guard for unknown persisted log-level values.
getNextRuntimeLogLevel Cycle through supported log levels.
createRuntimeLogger Create a prefixed console logger controlled by a log-level getter.
getAvailableLocalStorage Safely access localStorage when available.
removeStorageKeysMatching Best-effort removal for keys matching a predicate.
removeStorageNamespace Remove all keys under a caller-owned storage prefix.
removeScoreStorageKeys Remove score-like keys under a caller-owned storage prefix.
clampZoomPercent Clamp manual zoom values.
getSteppedZoomPercent Snap manual zoom values to a configured step.
getZoomScale Convert a zoom percent to a scale multiplier.
formatZoomPercent Format zoom percentages for settings UI.
getViewportScale Calculate responsive scale from viewport and reference dimensions.
getManualViewportScale Combine responsive viewport scale with a manual scale multiplier.
const logger = createRuntimeLogger({
  getLevel: () => options.logLevel,
  prefix: "[My Game]",
});

logger.warning("Resetting scores");
removeScoreStorageKeys("myGame.");

📺 Display Filters

Export Use It For
displayFilterModes Ordered preset list for settings menus.
displayFilterModeLabels User-facing labels for built-in display filter modes.
displayFilterSettingKeys Ordered setting keys for custom filter controls.
displayFilterSettingLabels User-facing labels for individual filter settings.
displayFilterSettingDescriptions Short descriptions for settings UI.
displayFilterPresets Built-in CRT/VHS/off settings.
defaultCustomDisplayFilterSettings Default custom settings object.
defaultDisplayFilterRuntimeBoosts Zeroed temporary boost values.
normalizeDisplayFilterIntensity Clamp unknown values to integer 0..100.
normalizeDisplayFilterSettings Normalize partial or untrusted settings into a complete settings object.
getDisplayFilterSettingsForMode Resolve preset/custom settings plus runtime boosts into effective settings.
const settings = getDisplayFilterSettingsForMode(
  "arcade-crt",
  defaultCustomDisplayFilterSettings,
  { explosionBloomBoost: 20 }
);

applyCanvasFilter(settings);

The helpers produce settings data only. Games choose how to render scanlines, masking, curvature, bloom, and other presentation effects.

🏆 Achievements

Export Use It For
createAchievementState Normalize persisted achievement state into unlocked, unlocked-at, and progress maps.
unlockAchievement Mark an achievement as unlocked without mutating previous state.
setAchievementProgress Set progress for one achievement and unlock it when its goal is reached.
addAchievementProgress Increment progress for one achievement and unlock it when its goal is reached.
getAchievementStatuses Combine definitions with current progress and unlock state for rendering.
const definitions = [
  {
    description: "Start a run.",
    id: "first-run",
    name: "First Run",
  },
  {
    description: "Collect 10 medals.",
    id: "medal-collector",
    name: "Medal Collector",
    progressGoal: 10,
  },
] as const;

let achievements = createAchievementState();
achievements = unlockAchievement(achievements, "first-run").state;
achievements = addAchievementProgress(
  definitions,
  achievements,
  "medal-collector",
  1
).state;

Achievement helpers are local game-state utilities. Remote leaderboard validation is handled by the high-score helpers. See Engine/Achievements/Achievements in Storybook for an interactive progress and unlock demo.

🏆 Achievement Notifications

Export Use It For
AchievementNotificationRenderer Queue and render animated canvas achievement unlock popups.
achievementNotificationEventName Default event name for event-driven notification enqueueing.
defaultAchievementNotificationLayout Default popup width, height, icon size, margin, and slide distance.
defaultAchievementNotificationTheme Default popup colors.
defaultAchievementNotificationTiming Default slide, hold, and exit durations.
const renderer = new AchievementNotificationRenderer({
  context,
  getViewport: () => ({ width: canvas.width, height: canvas.height }),
});

renderer.enqueue({
  name: "Wave Breaker",
  description: "Clear three waves.",
});
renderer.render();

The renderer works directly with canvas contexts. Games own their achievement definitions, icon assets, and render loop timing.

🏅 High Scores

Backend code can import high-score validation helpers without importing the whole engine root:

import {
  createHighScoreServerRunReceipt,
  validateHighScoreServerRunReceipt,
  validateHighScoreSubmission,
} from "arcade-engine/high-scores";
Export Use It For
createHighScoreManager Create a configurable local leaderboard and optional remote-sync controller.
createHighScoreIntegrity Create receipt-backed integrity data for a score submission.
validateHighScoreIntegrity Verify score, stats, settings, receipt, and submitted-at values still match integrity data.
validateHighScoreSubmission Validate unknown backend payloads before accepting remote leaderboard rows.
createHighScoreServerRunReceipt Issue a signed run receipt and matching stored receipt record for a backend route.
validateHighScoreServerRunReceipt Verify a submitted run receipt against a stored token hash, expiry, and used state.
createHighScoreRunToken Sign a runId:issuedAt pair with HMAC SHA-256.
hashHighScoreRunToken Hash a submitted receipt token for storage comparison.
areHighScoreTokenHashesEqual Compare token hashes without early exit.
isHighScorePlausible Check stat limits and weighted score budgets.
getHighScorePlausibilityReasons Return machine-readable plausibility failures.
getHighScoreStatValues Parse numeric stat lines such as Enemies: 12.
normalizeHighScoreName Normalize arcade-style score names.
sortHighScores Sort score entries by score, timestamp, and name.
isHighScoreEntry Type guard for public score rows.
isHighScoreIntegrity Type guard for score integrity payloads.
isHighScoreRunReceipt Type guard for run receipts.
isHighScoreServerRunRecord Type guard for stored backend receipt records.
isHighScoreServerRunRecordUsable Check whether a stored receipt record is unused and unexpired.
hashHighScoreText Stable non-cryptographic text hash used by integrity helpers.
const scores = createHighScoreManager({
  apiBasePath: "/api/scores",
  defaultScores: [],
  gameVersion: "1.0.0",
  storageKey: "myGame.highScores",
});

scores.saveHighScore("ACE", 12000, ["Enemies: 10"]);
const validation = validateHighScoreSubmission(payload, {
  isRunReceiptTrusted: (run) => trustedRunIds.has(run.runId),
  rules: {
    baseScoreBudget: 1000,
    maxScore: 1000000,
    scoreBudget: [
      { stat: "Enemies", points: 500 },
      { stat: "Bosses", points: 5000 },
    ],
  },
});

if (!validation.accepted) {
  throw new Error(validation.error);
}
const { receipt, record } = await createHighScoreServerRunReceipt({
  randomUUID: crypto.randomUUID,
  secret: process.env.HIGH_SCORE_SECRET!,
  ttlMs: 5 * 60 * 1000,
});

await runs.insert(record);
return receipt;
const validation = validateHighScoreSubmission(payload, {
  rules: scoreRules,
});

if (!validation.accepted) {
  throw new Error(validation.error);
}

const record = await runs.find(validation.run.runId);
const trusted = await validateHighScoreServerRunReceipt(validation.run, record, {
  secret: process.env.HIGH_SCORE_SECRET!,
});

if (!trusted) {
  throw new Error("invalid_run_receipt");
}

Use these helpers alongside your API routes, score storage, used-receipt updates, and rate limits. See Engine/Player Data/High Scores in Storybook for a local leaderboard and validation demo.

🎞️ Sprite Animation

Export Use It For
getSpriteFrameIndex Frame timing from elapsed seconds, animation FPS, and frame count.
getSpriteSheetFrame Convert a frame index into GameArena.renderSprite frame data.
getAnimatedSpriteFrame Get timed sprite frame data in one call.
const frame = getAnimatedSpriteFrame({
  columns: 4,
  elapsedSeconds,
  fps: 12,
  frameCount: 8,
  frameHeight: 16,
  frameWidth: 16,
});

arena.renderSprite(spriteImage, frame);

🧩 Grid And Box Helpers

Export Use It For
getGridSize Pixel dimensions for a grid definition.
getGridCell Top-left pixel coordinates for a grid cell.
getGridCellCenter Center pixel coordinates for a grid cell.
getGridPosition Grid coordinates from pixel coordinates.
isInsideGrid Cell bounds checks.
clampGridPosition Clamping a cell to the grid.
snapToGrid Snapping pixel coordinates into a valid grid cell.
clamp Numeric clamp utility used by box helpers.
moveBy Move a velocity-bearing rectangle over time.
detectBoxCollision Axis-aligned rectangle overlap.
containsBox Rectangle containment.
keepBoxInside Clamp a rectangle inside bounds.
getBoxCenter Rectangle center point.
const nextPaddle = keepBoxInside(moveBy(paddle, delta), arenaBounds);
const hit = detectBoxCollision(ball, brick);

🧲 Physics

Export Use It For
applyGravity2D Apply gravity, velocity, floor clamping, and optional bounce to a 2D body.
applyGravity3D Apply vertical gravity while preserving depth movement for a 3D body.
createRagdoll2D Create a small linked 2D ragdoll point/constraint skeleton.
createRagdoll3D Create a linked 3D ragdoll point/constraint skeleton.
stepRagdoll2D Step a 2D ragdoll with Verlet-style gravity and constraint solving.
stepRagdoll3D Step a 3D ragdoll with gravity, depth, and constraint solving.
let body = { posX: 20, posY: 0, velocityY: 0 };

body = applyGravity2D(body, {
  delta,
  floorY: 240,
  gravity: 980,
});

🧭 Viewport And Debug Vectors

Export Use It For
getViewportRadius Radius from viewport dimensions.
getViewportPaddedRadius Radius with padding.
getViewportAreaScale Scale values against viewport area.
getScaledViewportLimit Responsive spawn/entity limits.
getViewportScale Responsive UI/game scale from a reference viewport.
getManualViewportScale Responsive viewport scale plus manual zoom scale.
clampZoomPercent Clamp manual zoom percentages.
getSteppedZoomPercent Snap zoom percentages to a menu/control step.
getZoomScale Convert zoom percentage to a scale multiplier.
formatZoomPercent Format zoom values for display.
drawDebugVectors Canvas overlays for heading, velocity, and target vectors.

📷 Camera

Export Use It For
getFollowCamera 2D camera follow behavior with optional dead zone, smoothing, and world bounds.
const camera = getFollowCamera({
  current: previousCamera,
  deadZone: { width: 80, height: 48 },
  smoothing: 0.2,
  target: player,
  viewport,
  worldBounds,
});

🎨 Canvas Rendering

Export Use It For
fillCanvasWithTrail Frame clears with fading after-images.
drawCanvasLine Simple line drawing.
drawCanvasPolygon Filled and optionally stroked polygons.
parseHexColor Hex color parsing.
colorWithAlpha Hex color to RGBA string.
shadeHexColor Hex color shading.
fillCanvasWithTrail(context, canvas, "#05070a", 0.18);
drawCanvasLine(context, from, to, "#f6e05e", 2);

💡 Ray Tracing

Export Use It For
createRayTracingRectangle Create a clockwise rectangle polygon from top-left coordinates and size.
createRayTracingBoundsPolygon Convert render bounds into a rectangular clipping polygon.
getRayTracingPolygonSegments Convert a polygon into line segments for intersection checks.
getRayTracingSegments Combine bounds and occluder polygons into a segment list.
traceRay Find the nearest segment hit from an origin and angle.
traceVisibilityPolygon Build sorted visibility hits for a light/viewpoint clipped by bounds and occluders.
traceLightBounces Build direct visibility plus capped diffuse bounce layers.
const bounds = { height: canvas.height, width: canvas.width };
const occluders = [
  createRayTracingRectangle(120, 90, 64, 48),
  createRayTracingRectangle(260, 140, 96, 32),
];
const visibility = traceVisibilityPolygon({ x: 80, y: 120 }, bounds, occluders);

drawCanvasPolygon(context, visibility, "rgba(255, 220, 120, 0.22)");
const layers = traceLightBounces({ x: 80, y: 120 }, bounds, occluders, {
  bounces: 1,
  lightColor: "#ffd36f",
  surfaceColorMix: 0.4,
});

These helpers only calculate 2D geometry. Games own the final rendering style, color blending, gradients, shadow treatment, and interaction model. Bounce requests are capped to 0..3 layers for now, and the demo assumes low-reflectivity materials with steep attenuation. Bounds and occluders can provide surfaceColor values so bounced layers inherit some of the material color they hit. See Engine/Rendering/Ray Traced Apartment in Storybook for a Canvas 2D lighting demo with draggable furniture, a movable lamp, per-light intensity controls, one bounce enabled by default, bounce attenuation tuning, a ray-guide toggle, and monochrome TV-static flicker.

🕹️ 2.5D Projection

Export Use It For
wrapDepth Looping depth values through a fixed range.
getLoopedDepth Repeating starfields, lanes, gates, or scenery by depth.
getDepthProgress Normalized depth progress for alpha, size, and intensity.
getPerspectiveScale Scale from depth.
projectPerspectivePoint Project a 3D point into 2D canvas coordinates.
projectIsometricPoint Convert a 3D grid point into isometric 2D coordinates.
getIsometricTileCorners Tile diamond corners for isometric drawing.
getIsometricWallSide Extruded wall side polygons.
const projected = projectPerspectivePoint(
  { x: laneX, y: 120, z: depth },
  { width: canvas.width, height: canvas.height }
);

🏃 Arcade Motion

Export Use It For
getFirstPersonCamera First-person center/horizon framing from viewport and look input.
getLoopedScrollerPosition Wrapped side-scroller scenery and platform positions.
getSideScrollerActorPosition Wrapped actor positions with visibility and progress for obstacles, enemies, pickups, or platforms.
getSideScrollerJumpY Simple jump and bob arcs.
getSpatialAudioPan Clamp game-space source position into browser pan range.
getSpatialAudioDepth Convert source distance into visual depth for 2.5D audio scenes.
const camera = getFirstPersonCamera(viewport, {
  centerDrift: 78,
  horizonRatio: 0.47,
  look: pointer,
});

🔊 Spatial Audio Math

Export Use It For
getDistanceGain Convert listener/source distance into a gain value.
getSpatialAudioMix Calculate distance, pan, and gain for a source relative to a listener.
const mix = getSpatialAudioMix({
  listener: player,
  listenerRange: 240,
  maxDistance: 480,
  source: pickup,
});

sound.setPan(mix.pan);

🌧️ Screen And Atmospheric Effects

Screen effects render above the world and below HUD/UI by default. Atmospheric effects render as world-space weather or air particles before HUD and screen overlays.

Export Use It For
ScreenEffectManager Register, enable, disable, update, and render stackable screen effects by id.
createScreenDropletsEffectDefinition Camera, visor, or screen rain droplets.
createScreenFireEffectDefinition Player fire or burn feedback.
createScreenFrostEffectDefinition Player cold or frost feedback.
createScreenPoisonEffectDefinition Toxic, sickly player-state feedback.
createScreenLowHealthEffectDefinition Red pulsing low-health danger feedback.
createScreenShockEffectDefinition Short electric damage flashes, arcs, and glitch slices.
createScreenSpeedBoostEffectDefinition Pixel speed lines and fast-motion streaks.
createEnvironmentHeatEffectDefinition Warm tint, shimmer bands, and heat ripples.
createEnvironmentFrostEffectDefinition Edge frost, crystal clusters, and breath mist.
createEnvironmentFireEffectDefinition Edge flames, embers, smoke, and warm flicker.
createEnvironmentUnderwaterEffectDefinition Blue-green tint, slow wave distortion, bubbles, and debris.
AtmosphericRainEffect / createAtmosphericRainEffect Pixel rain streaks, wind slant, small splashes, and optional player-relative motion.
AtmosphericSnowEffect / createAtmosphericSnowEffect Layered snow drift with optional accumulation and optional player-relative motion.
AtmosphericAshEmberEffect / createAtmosphericAshEmberEffect Drifting ash plus rising flickering embers with optional player-relative motion.
const screenEffects = new ScreenEffectManager();
screenEffects.register(createScreenLowHealthEffectDefinition());
screenEffects.register(createEnvironmentUnderwaterEffectDefinition());

screenEffects.enable("screen-low-health", { intensity: 0.6 });
screenEffects.enable("environment-underwater", { intensity: 0.4 });

const rain = createAtmosphericRainEffect({
  density: "heavy",
  wind: 120,
});

rain.update(deltaTime, viewport);
rain.render(context, viewport);

screenEffects.update(deltaTime, viewport);
screenEffects.render(context, viewport);

✨ Procedural Background Stars

Export Use It For
ProceduralStarfield Generated pixel stars that scroll opposite player x/y motion and fly toward or away from a centre point on the z-axis.
createProceduralStarfield Factory for creating a configured ProceduralStarfield.
const stars = createProceduralStarfield({
  starCount: 180,
  velocityX: playerVelocity.x,
  velocityY: playerVelocity.y,
  velocityZ: playerVelocity.z,
});

stars.update(deltaTime, viewport);
stars.render(context, viewport);

Use positive velocityZ for forward fly-through motion, where stars expand away from the centre. Use negative velocityZ to make the field recede toward the centre.

🧊 Cube Clusters

Export Use It For
createCubeClusterFromPattern Build voxel-like block models from text patterns.
createPlasmaLinks Generate links between nearby blocks.
centerCubeCluster Center block coordinates around their bounds center.
getCubeClusterBounds Cluster min/max bounds.
getCubeClusterCenter Cluster center point.
cloneCubeBlock Copy a cube block.
createExplosionBlocks Convert blocks into moving explosion debris.
stepExplosionBlocks Advance explosion position, velocity, gravity, drag, and opacity.
getVisibleExplosionBlocks Filter faded debris.
normalizeVector Normalize a 3D vector.
getVectorDistance Distance between 3D points.
const cluster = createCubeClusterFromPattern([["###", " # "]]);
const blocks = centerCubeCluster(cluster.blocks);
const explosion = createExplosionBlocks(blocks, { force: 6 });

🧾 Public Types

The package exports TypeScript types for public data shapes, including:

  • Arena, sound, ticker, input, multiplayer, animation, camera, coordinate, heading, sprite, and render options.
  • Achievement, high-score, grid, box, physics, viewport, debug-vector, debug overlay, procedural-starfield, screen-effect, atmospheric-effect, canvas color, projection, arcade-motion, spatial-audio, cube-cluster, and explosion types.

Use these types when building reusable game systems on top of Arcade Engine.