install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/TerminalSkills/skills/excalibur" ~/.claude/skills/comeonoliver-skillshub-excalibur && rm -rf "$T"
manifest:
skills/TerminalSkills/skills/excalibur/SKILL.mdsource content
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
instead of constructor for game logiconPostUpdate - Collision types — Use
for moving entities,Active
for static platforms,Fixed
for triggers/sensorsPassive - Scene transitions —
to pass data between scenesengine.goToScene("name", { sceneActivationData }) - Tiled plugin — Use the official Tiled plugin for level design; supports tile layers, object layers, and custom properties
- Actions API — Chain animations:
for cutscenes and effectsactor.actions.moveTo(100, 100, 200).delay(500).fade(0, 1000) - Event system — Use typed events (
,on("precollision")
) for clean game logicon("kill") - Resource loading — Define all assets in a loader; Excalibur shows a loading screen automatically