> excalibur
You are an expert in Excalibur.js, the TypeScript-first 2D game engine built for the web. You help developers build browser games using Excalibur's Actor system, Scene management, Tiled integration, physics, animation, sound, and input handling — with first-class TypeScript support, excellent documentation, and a focus on developer experience over raw performance.
curl "https://skillshub.wtf/TerminalSkills/skills/excalibur?format=md"Excalibur.js — TypeScript-First 2D Game Engine
You are an expert in Excalibur.js, the TypeScript-first 2D game engine built for the web. You help developers build browser games using Excalibur's Actor system, Scene management, Tiled integration, physics, animation, sound, and input handling — with first-class TypeScript support, excellent documentation, and a focus on developer experience over raw performance.
Core Capabilities
Game Setup
// src/main.ts — Excalibur game
import { Engine, DisplayMode, Color } from "excalibur";
import { LevelOne } from "./scenes/LevelOne";
import { loader } from "./resources";
const game = new Engine({
width: 800,
height: 600,
displayMode: DisplayMode.FitScreen,
backgroundColor: Color.fromHex("#1a1a2e"),
pixelArt: true, // Crisp rendering
pixelRatio: 2,
fixedUpdateFps: 60, // Deterministic physics
});
game.addScene("level-one", new LevelOne());
game.start(loader).then(() => { // Preload assets
game.goToScene("level-one");
});
Actors and Components
// src/actors/Player.ts
import { Actor, Color, vec, Keys, CollisionType, Animation, SpriteSheet } from "excalibur";
import { Resources } from "../resources";
export class Player extends Actor {
private speed = 200;
private jumpForce = -400;
private health = 3;
private isGrounded = false;
constructor(x: number, y: number) {
super({
pos: vec(x, y),
width: 16,
height: 24,
collisionType: CollisionType.Active, // Moves and collides
color: Color.Green,
});
}
onInitialize(engine: Engine) {
// Sprite sheet animations
const spriteSheet = SpriteSheet.fromImageSource({
image: Resources.HeroSheet,
grid: { rows: 4, columns: 6, spriteWidth: 16, spriteHeight: 24 },
});
const idle = Animation.fromSpriteSheet(spriteSheet, [0, 1, 2, 3], 200);
const run = Animation.fromSpriteSheet(spriteSheet, [6, 7, 8, 9, 10, 11], 100);
const jump = Animation.fromSpriteSheet(spriteSheet, [12, 13], 150);
this.graphics.add("idle", idle);
this.graphics.add("run", run);
this.graphics.add("jump", jump);
this.graphics.use("idle");
// Ground detection
this.on("postcollision", (evt) => {
if (evt.side === "Bottom") this.isGrounded = true;
});
}
onPreUpdate(engine: Engine, delta: number) {
const kb = engine.input.keyboard;
let moving = false;
if (kb.isHeld(Keys.ArrowLeft)) {
this.vel.x = -this.speed;
this.graphics.flipHorizontal = true;
moving = true;
} else if (kb.isHeld(Keys.ArrowRight)) {
this.vel.x = this.speed;
this.graphics.flipHorizontal = false;
moving = true;
} else {
this.vel.x = 0;
}
if (kb.wasPressed(Keys.Space) && this.isGrounded) {
this.vel.y = this.jumpForce;
this.isGrounded = false;
this.graphics.use("jump");
} else if (moving) {
this.graphics.use("run");
} else {
this.graphics.use("idle");
}
}
takeDamage(amount: number) {
this.health -= amount;
// Flash red
this.actions.blink(100, 100, 5);
if (this.health <= 0) {
this.scene?.engine.goToScene("game-over");
}
}
}
Scenes and Tiled Maps
// src/scenes/LevelOne.ts
import { Scene, Engine, TileMap, vec } from "excalibur";
import { TiledResource } from "@excaliburjs/plugin-tiled";
import { Player } from "../actors/Player";
import { Coin } from "../actors/Coin";
export class LevelOne extends Scene {
private tiledMap!: TiledResource;
onInitialize(engine: Engine) {
this.tiledMap = new TiledResource("/maps/level-1.tmx");
// Add tilemap to scene
this.tiledMap.addToScene(this);
// Get spawn point from Tiled object layer
const spawnPoint = this.tiledMap.getObjectsByName("PlayerSpawn")[0];
const player = new Player(spawnPoint.x, spawnPoint.y);
this.add(player);
// Camera follows player
this.camera.strategy.elasticToActor(player, 0.8, 0.9);
this.camera.zoom = 2;
// Spawn coins from object layer
this.tiledMap.getObjectsByType("coin").forEach((obj) => {
this.add(new Coin(obj.x, obj.y));
});
}
}
Installation
npm install excalibur
npm install @excaliburjs/plugin-tiled # Tiled map support
Best Practices
- TypeScript always — Excalibur is built in TypeScript; use it for full autocompletion and type safety
- Actor lifecycle — Override
onInitialize,onPreUpdate,onPostUpdateinstead of constructor for game logic - Collision types — Use
Activefor moving entities,Fixedfor static platforms,Passivefor triggers/sensors - Scene transitions —
engine.goToScene("name", { sceneActivationData })to pass data between scenes - Tiled plugin — Use the official Tiled plugin for level design; supports tile layers, object layers, and custom properties
- Actions API — Chain animations:
actor.actions.moveTo(100, 100, 200).delay(500).fade(0, 1000)for cutscenes and effects - Event system — Use typed events (
on("precollision"),on("kill")) for clean game logic - Resource loading — Define all assets in a loader; Excalibur shows a loading screen automatically
> related_skills --same-repo
> zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
> zoho
Integrate and automate Zoho products. Use when a user asks to work with Zoho CRM, Zoho Books, Zoho Desk, Zoho Projects, Zoho Mail, or Zoho Creator, build custom integrations via Zoho APIs, automate workflows with Deluge scripting, sync data between Zoho apps and external systems, manage leads and deals, automate invoicing, build custom Zoho Creator apps, set up webhooks, or manage Zoho organization settings. Covers Zoho CRM, Books, Desk, Projects, Creator, and cross-product integrations.
> zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
> zipkin
Deploy and configure Zipkin for distributed tracing and request flow visualization. Use when a user needs to set up trace collection, instrument Java/Spring or other services with Zipkin, analyze service dependencies, or configure storage backends for trace data.