ai-behavior-trees-util…
Engine-neutral behavior tree and utility AI code for NPCs in any language: Blackboard, reactive composites, decorators and…
Builds and debugs 2D browser game rendering with PixiJS v8: async init, Assets loading, the Container and Sprite scene graph, pointer dragging and v7-to-v8 migration. Use when a game or playable ad uses pixi.js, or on a blank canvas, clicks not firing, or drag stopping at the
Claude Code
$ npx -y skills add gamedev-skills/awesome-gamedev-agent-skills --skill pixijs-rendering --agent claude-code
Codex
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill pixijs-rendering -a codex -y
Cursor
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill pixijs-rendering -a cursor -y
Gemini CLI
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill pixijs-rendering -a gemini-cli -y
GitHub Copilot
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill pixijs-rendering -a github-copilot -y
OpenCode
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill pixijs-rendering -a opencode -y
Windsurf
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill pixijs-rendering -a windsurf -y
name: pixijs-rendering description: > Builds and debugs 2D browser game rendering with PixiJS v8: async init, Assets loading, the Container and Sprite scene graph, pointer dragging and v7-to-v8 migration. Use when a game or playable ad uses pixi.js, or on a blank canvas, clicks not firing, or drag stopping at the sprite edge. Not for dashboards or charts, Phaser (`phaser-core`) or 3D (`threejs-scene-setup`).
Sets up and structures a PixiJS **8.22** game renderer: the async `Application`, asset loading through `Assets`, the `Container` scene graph, the ticker loop, pointer events and render groups. PixiJS draws; it has no scenes, physics or input mapping. A game that wants those built in is usually better served by Phaser. With PixiJS you write the loop, the screen manager and the collision code yourself.
loading textures and sprite sheets, animating with the ticker, or handling pointer input.
(`threejs-scene-setup`). PixiJS v7 code (`new Application({...})`, `Loader`, `beginFill`) must be migrated first; the Gotchas list the renames.
1. **Read the installed version.** v8 changed boot, loading, Graphics and events, so v7 answers from memory break here. 2. **Create, then `await app.init({...})`.** The v8 constructor takes no options. Append `app.canvas` to the page. 3. **Load before you build.** `await Assets.load(...)` or a manifest bundle per screen; the returned `Texture` is what `Sprite` takes. 4. **Build the display list from `Container`s**, one per layer (world, effects, HUD). Child transforms are relative to the parent; later children draw on top. 5. **Run game logic in one ticker callback** scaled by `ticker.deltaMS / 1000` (seconds) or `ticker.deltaTime` (≈1 per 60 Hz frame). Keep rules in plain modules the callback calls. 6. **Turn on input per object** with `eventMode = 'static'`, then `on('pointerdown', ...)`. 7. **Clean up on screen changes**: `destroy()` what you remove and `Assets.unload()` what the next screen does not need. 8. **Verify** with [Verify](#verify).
import { Application, Assets, Sprite } from 'pixi.js';
const app = new Application();
await app.init({
background: '#1099bb',
resizeTo: window,
antialias: true,
// preference: 'webgpu', // a hint; default order is webgl, webgpu, canvas
});
document.body.appendChild(app.canvas);
Object.assign(window, { app }); // for the smoke check and console debugging (TS-safe)
const texture = await Assets.load('assets/bunny.png');
const bunny = new Sprite(texture);
bunny.anchor.set(0.5);
bunny.position.set(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(bunny);import { Container } from 'pixi.js';
const world = new Container(); // camera: move or scale this, not every sprite
const hud = new Container(); // added last, so it draws over the world
app.stage.addChild(world, hud);
world.position.set(-camera.x, -camera.y);
world.scale.set(2);app.ticker.add((ticker) => {
const dt = ticker.deltaMS / 1000; // seconds since the last frame
stepGame(state, input, dt); // rules live in a plain module
bunny.rotation += 1.5 * dt;
});bunny.eventMode = 'static'; // the v8 default 'passive' ignores the object itself
bunny.cursor = 'pointer';
bunny.on('pointerdown', () => { dragging = true; });
bunny.on('pointerup', () => { dragging = false; });
bunny.on('pointerupoutside', () => { dragging = false; });
// pointermove fires only over the object in v8; globalpointermove fires on every move.
bunny.on('globalpointermove', (event) => {
if (dragging) bunny.position.copyFrom(event.global);
});// addBundle works at any time; Assets.init({ manifest }) only works before the first load.
Assets.addBundle('level-1', [
{ alias: 'hero', src: 'assets/hero.png' },
{ alias: 'atlas', src: 'assets/characters.json' }, // TexturePacker JSON
]);
Assets.addBundle('level-2', [{ alias: 'boss', src: 'assets/boss.png' }]);
const level = await Assets.loadBundle('level-1');
const hero = new Sprite(level.hero);
Assets.backgroundLoadBundle('level-2'); // warm the next screen while this one playsconst background = new Container({ isRenderGroup: true });
app.stage.addChildAt(background, 0);
// Hundreds of static tiles go in here. Moving `background` stays cheap;
// adding and removing children every frame cancels the benefit.1. `npm run build` (or `npx tsc --noEmit`) passes. 2. Smoke-test in a headless browser. With the dev server running and `window.app` exposed (Pattern 1), run `node smoke.mjs <url>` after `npm i -D playwright` and `npx playwright install chromium`. Without browser automation, ask the user to open the page and report the console output and what is drawn.
// smoke.mjs: fails on page errors; prints the backend and the display list size.
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
const errors = [];
page.on('pageerror', (e) => errors.push(e.message));
page.on('console', (m) => { if (m.type() === 'error') errors.push(m.text()); });
await page.goto(process.argv[2]);
await page.waitForFunction(() => window.app?.renderer, null, { timeout: 15000 });
await page.waitForTimeout(1000); // let the first assets load
const state = await page.evaluate(() => ({
backend: window.app.renderer.name, // 'webgl', 'webgpu' or 'canvas'
stageChildren: window.ap<img src="docs/assets/awesome-gamedev-agent-skills-banner.png" width="820" alt="awesome-gamedev-agent-skills — game-dev skills for AI coding agents.
Engine-neutral behavior tree and utility AI code for NPCs in any language: Blackboard, reactive composites, decorators and…
Engine-neutral game audio technique: bus layout, volume sliders in decibels, loudness, ducking music under dialogue, adaptive…
Builds and tunes game cameras, engine-neutral with Godot and Cinemachine 3 mappings: 2D follow with deadzone and look-ahead,…
Plans, generates or sources, and validates consistent game art: style guides, sprites, pixel art, tilesets, icons and textures,…
Builds engine-neutral branching dialogue with Ink, Yarn Spinner or a small JSON graph runner: lines, choices, conditions,…
Designs engine-neutral enemy and NPC AI: picks FSM, behavior tree, utility or GOAP, and builds perception, steering and A*…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.