agentleFS
freemafreema/ai-skills/skills/phaser-gamedev/SKILL.md

phaser-gamedev

Skill5 starsChanged 20 days agoMITView on GitHub

Build 2D browser games with Phaser 3 (JS/TS): scenes, sprites, physics (Arcade/Matter), tilemaps (Tiled), animations, input. Trigger: 'Phaser scene', 'Arcade physics', 'tilemap', 'Phaser 3 game'.

2 other projects use a version of this, 1 of them edited.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

8 rules. About 0 are common, 4 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Measure the asset: before writing loader code—never guess frame dimensions

    line 30
  2. Distinctive:

    Character sprites use SQUARE frames: If you calculate frameWidth=56, try 56 for height first

    line 31
  3. Distinctive:

    Read these BEFORE working on the relevant feature:

    line 40
  4. Very specific:

    Frame-rate independence: Use delta for motion and timers.

    line 85
  5. Very specific:

    When textures are larger than display size (e.g.

    line 91
  6. Distinctive:

    When drawing Graphics effects (brake lights, nitro flames, etc.) on top of sprite-based game objects:

    line 167
  7. Very specific:

    After g.translateCanvas(x, y) + g.rotateCanvas(angle), the local coordinate origin is the sprite center.

    line 175
  8. Very specific:

    If a sprite faces south but angle=0 means north: add Math.PI to sprite rotation, but keep Graphics rotateCanvas(car.angle) as-is (Graphics …

    line 193

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Phaser Game Development

Build 2D browser games using Phaser 3's scene-based architecture and physics systems.


Before Starting A New Game Or Touching An Existing One

Read read-before-implement.md first. Three-layer reading order (skill docs → target game → shared helpers) and the pre-implementation output checklist. Skipping this is the #1 source of invented APIs and wrong assumptions.

Before merging to main, run the relevant checks in pre-release-audit.md — 7 reactive error signatures + 7 proactive consistency checks (asset keys, scene registration, reloadDocument on game links, touch-controls cleanup, viewport restart guard).

When reaching for abstraction, consult game-patterns.md first — it catalogs composition patterns (BehaviorManager, FSM, TurnManager, WaveManager, CardManager, DialogueManager) with explicit "when to extract" vs "stay ad-hoc" signals. Prevents premature abstraction.


STOP: Before Loading Any Spritesheet

Read spritesheets-nineslice.md FIRST.

Spritesheet loading is fragile—a few pixels off causes silent corruption that compounds into broken visuals. The reference file contains the mandatory inspection protocol.

Quick rules (details in reference):

  1. Measure the asset before writing loader code—never guess frame dimensions
  2. Character sprites use SQUARE frames: If you calculate frameWidth=56, try 56 for height first
  3. Different animations have different frame sizes: A run cycle needs wider frames than idle; an attack needs extra width for weapon swing. Measure EACH spritesheet independently
  4. Check for spacing: Gaps between frames require spacing: N in loader config
  5. Verify the math: imageWidth = (frameWidth × cols) + (spacing × (cols - 1))

Reference Files

Read these BEFORE working on the relevant feature:

When working on...Read first
Starting a new game, or editing a scene you haven't touched recentlyread-before-implement.md
Pre-merge / pre-release audit, or diagnosing a runtime errorpre-release-audit.md
Deciding whether to extract an FSM / BehaviorManager / TurnManager / WaveManager / CardManager / DialogueManagergame-patterns.md
Loading ANY spritesheetspritesheets-nineslice.md
Nine-slice UI panelsspritesheets-nineslice.md
Config, scenes, objects, input, animationscore-patterns.md
Tiled tilemaps, collision layerstilemaps.md
Physics tuning, groups, poolingarcade-physics.md
Scrolling platforms, custom body sizesarcade-physics.md (Static vs Dynamic section)
Performance issues, object poolingperformance.md
Keyboard input, SPACE key, canvas focuskeyboard-input.md
Raycasting (Wolf3D-style FPS), doors, transparent gates, billboard sprites, enemy collision, secret walls, wall-mounted decals, torch lighting, fisheye fix, texture clipping, weapon sprites, enemy animation, level data integrityraycasting.md
Procedural dungeon generation, BSP splitting, corridor carving, door placement, wall-door-wall, level validationprocedural-dungeon-gen.md

Architecture Decisions (Make Early)

Before building, decide:

  • What scenes does this game need? (Boot, Menu, Game, UI overlay, GameOver)
  • What are the core entities and how do they interact?
  • What physics model fits? (Arcade for speed, Matter for realism, None for menus)
  • What input methods? (keyboard/gamepad/touch)

Physics System Choice

SystemUse When
ArcadePlatformers, shooters, most 2D games. Fast AABB collisions
MatterPhysics puzzles, ragdolls, realistic collisions. Slower, more accurate
NoneMenu scenes, visual novels, card games

Core Principles

  1. Scene-first architecture: Organize code around scene lifecycle and transitions
  2. Composition over inheritance: Build entities from sprite/body/controllers, not deep class trees
  3. Physics-aware design: Choose collision model early; don't retrofit physics late
  4. Asset pipeline discipline: Preload everything; reference by keys; keep loading deterministic
  5. Frame-rate independence: Use delta for motion and timers; avoid frame counting

CRITICAL: Scaled Sprites + Physics Bodies

When textures are larger than display size (e.g. AI-generated assets), body.setSize() is multiplied by sprite scale!

WRONG — body becomes tiny (5px instead of 80px):

sprite.setDisplaySize(80, 12); // scale = 80/1200 = 0.067
sprite.body.setSize(80, 12); // actual body = 80 * 0.067 = 5px!

CORRECT — use FRAME (texture) size, scale applies automatically:

sprite.setDisplaySize(80, 12);
const body = sprite.body as Phaser.Physics.Arcade.Body;
body.setSize(sprite.frame.width, sprite.frame.height); // body = 1200 * 0.067 = 80px ✓

For static bodies (bricks, platforms), also call updateFromGameObject():

brick.setDisplaySize(40, 16);
const body = brick.body as Phaser.Physics.Arcade.StaticBody;
body.setSize(brick.frame.width, brick.frame.height);
body.updateFromGameObject(); // REQUIRED for static bodies!

CRITICAL: Arcade physics bodies CANNOT rotate

setAngle() / setRotation() rotates the VISUAL sprite only. The physics body stays axis-aligned (AABB). This means rotated wall sprites have wrong collision shapes.

WRONG — body stays 64×32 horizontal even though sprite is rotated 90°:

wall.setAngle(90);
wall.body.setSize(64, 32); // still horizontal!

CORRECT — separate visual from collision:

// Visual only (no physics)
this.add.image(x, y, "wall").setAngle(90);

// Invisible collision zone
const zone = this.add.zone(x, y, 16, span);
this.physics.add.existing(zone, true); // static body
wallGroup.add(zone);

Obstacle collision groups pattern

Split obstacles into separate StaticGroups when different entities need different collision rules:

this.walls = this.physics.add.staticGroup(); // invisible zones
this.trees = this.physics.add.staticGroup(); // visible + physics

// Walls block player only (enemies walk through to enter arena)
this.physics.add.collider(this.player, this.walls);
// Trees block everyone
this.physics.add.collider(this.player, this.trees);
this.physics.add.collider(this.enemyPool, this.trees);

CRITICAL: Keyboard input — canvas focus problem

Read keyboard-input.md for the full solution.

Phaser's keyboard only works when canvas has focus. When embedded in a React page, canvas loses focus constantly (user clicks tabs, buttons, scrolls). keyboard.target: window alone does NOT fix this.

Required: Window-level capture-phase listener that re-focuses canvas + re-dispatches the event. Plus addCapture(SPACE) in each scene that uses SPACE.


Graphics Overlays on Sprites (Brake Lights, Flames, Effects)

When drawing Graphics effects (brake lights, nitro flames, etc.) on top of sprite-based game objects:

Sprite canvas ≠ car body

AI-generated sprites have transparent padding — the visible content is smaller than the PNG canvas. Always crop sprites first (process_sprite with auto-crop) so the PNG edges match the pixel art edges. Otherwise, effects positioned at halfW/halfH will float outside the visible car.

Coordinate alignment

After g.translateCanvas(x, y) + g.rotateCanvas(angle), the local coordinate origin is the sprite center. Position effects relative to the display size (which maps to cropped sprite edges):

const halfW = CAR_DRAW_W / 2;
const halfH = CAR_DRAW_H / 2;
// Brake lights at rear corners (car body is ~55% of canvas width)
const sideX = halfW * 0.38; // actual car edge, NOT halfW
const rearY = halfH - 4; // just inside rear edge

Multi-layer effects look better

  • Brake lights: outer glow circle (large, low alpha) + inner 2×2px rect (bright)
  • Nitro flame: 3 layers — outer (orange), mid (yellow), core (white-yellow) with sin-based flicker
  • Dual exhaust: 2 separate small flames with independent flicker phases

Sprite rotation offset

If a sprite faces south but angle=0 means north: add Math.PI to sprite rotation, but keep Graphics rotateCanvas(car.angle) as-is (Graphics follow physics convention, sprite gets the visual flip).


Anti-Patterns

Anti-PatternProblemSolution
Global state on windowScene transitions break stateUse scene data, registries
Loading in create()Assets not ready when referencedLoad in preload(), use Boot scene
Frame countingGame speed varies with FPSUse delta / 1000
Matter for simple collisionsUnnecessary complexityArcade handles most 2D games
One giant sceneHard to extendSeparate gameplay/UI/menus
Magic numbersImpossible to balanceConfig objects, constants
No object poolingGC stuttersGroups with setActive(false)
body.setSize(displayW, displayH) on scaled spritesBody is multiplied by scale → tinyUse body.setSize(frame.width, frame.height)
StaticBody + setSize() + updateFromGameObject()updateFromGameObject() overwrites custom size every frameUse immovable dynamic body (setImmovable(true)) — see arcade-physics.md
setAngle() on physics spritesVisual rotates but body stays axis-aligned (AABB)Use invisible zones for collision, sprites for visual only
Constant setAlpha(0.5) for invincibilityCharacter looks broken/ghostlyUse blink tween (alpha 1↔0.3, duration 80, yoyo)
Loading non-existent sprites in preload()Silent 404 errors on every game loadOnly load files that exist; use !textures.exists() + programmatic fallback in create()
2500 individual add.image() for tile grid2500 game objects = slowUse RenderTexture — draw all tiles onto one texture

Variation Guidance

Outputs should vary based on:

  • Genre (platformer vs top-down vs shmup)
  • Target platform (mobile touch, desktop keyboard, gamepad)
  • Art style (pixel art scaling vs HD smoothing)
  • Performance envelope (many sprites → pooling; few sprites → simpler code)

Remember

Phaser provides powerful primitives—scenes, sprites, physics, input—but architecture is your responsibility.

Think in systems: define the scenes, define the entities, define their interactions—then implement.

Codex can build complete, polished Phaser games. These guidelines illuminate the path—they don't fence it.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.