Install
$ agentstack add skill-pradeepmouli-skillit-handwritten-approach ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
PixiJS v8 Skill
When to Use
- Building 2D games, interactive experiences, or animated UIs in the browser
- Rendering many sprites, particles, or animated objects at high frame rates
- Need hardware-accelerated 2D graphics with WebGL or WebGPU
Avoid When
- Simple static UI — use CSS/HTML instead
- Server-side rendering without a canvas environment
- 3D scenes — use Three.js or Babylon.js instead
Critical Pitfalls (NEVER rules)
NEVER pass options to the Application constructor — always use await app.init().
// WRONG (deprecated, triggers warning in v8)
const app = new Application({ width: 800 });
// RIGHT
const app = new Application();
await app.init({ width: 800, height: 600 });
NEVER use app.view — it was renamed to app.canvas.
// WRONG
document.body.appendChild(app.view);
// RIGHT
document.body.appendChild(app.canvas);
NEVER use Texture.from(url) to load a URL that hasn't been loaded yet — load through Assets first.
// WRONG — will return empty texture if not preloaded
const tex = Texture.from('https://example.com/sprite.png');
// RIGHT
await Assets.load('https://example.com/sprite.png');
const tex = Texture.from('https://example.com/sprite.png');
// Or simply:
const tex = await Assets.load('sprite.png');
NEVER use the v7 Graphics API (beginFill / drawRect / endFill) — v8 changed the order.
// WRONG (v7 style)
g.beginFill(0xff0000).drawRect(0, 0, 100, 100).endFill();
// RIGHT (v8 style: shape first, then fill/stroke)
g.rect(0, 0, 100, 100).fill(0xff0000);
NEVER add children to leaf nodes (Sprite, Graphics, Text) — only Container accepts children.
// WRONG
const sprite = new Sprite(texture);
sprite.addChild(otherSprite); // deprecated / will warn
// RIGHT
const container = new Container();
container.addChild(sprite);
container.addChild(otherSprite);
NEVER use DisplayObject — it was removed. Everything is a Container.
NEVER use container.name — it was renamed to container.label.
NEVER use SCALE_MODES.NEAREST enum — use the string 'nearest' instead.
NEVER use container.cacheAsBitmap = true — call container.cacheAsTexture(true) instead.
NEVER use container.getBounds() expecting a Rectangle — v8 returns a Bounds object; use .rectangle.
const rect = container.getBounds().rectangle;
NEVER use Ticker.shared.add(dt => ...) expecting delta time — the callback now receives the Ticker instance.
// WRONG
Ticker.shared.add((dt) => {
sprite.x += dt;
});
// RIGHT
Ticker.shared.add((ticker) => {
sprite.x += ticker.deltaTime;
});
NEVER import from sub-packages like @pixi/sprite — v8 uses a single package.
// WRONG
import { Sprite } from '@pixi/sprite';
// RIGHT
import { Sprite } from 'pixi.js';
NEVER use utils.isMobile — import directly.
// WRONG
import { utils } from 'pixi.js';
utils.isMobile.any();
// RIGHT
import { isMobile } from 'pixi.js';
isMobile.any();
NEVER use settings.RESOLUTION — configure via AbstractRenderer.defaultOptions or init options.
// WRONG
settings.RESOLUTION = 2;
// RIGHT
await app.init({ resolution: window.devicePixelRatio });
NEVER use updateTransform() for per-frame logic — use onRender instead.
// RIGHT
mySprite.onRender = () => {
/* custom per-frame logic */
};
NEVER use ParticleContainer with Sprite children — v8 requires Particle objects.
// WRONG
container.addChild(new Sprite(texture));
// RIGHT
container.addParticle(new Particle(texture));
Key Classes — Decision Table
| Goal | Class to Use | Notes | | ----------------------------- | -------------------------------------- | -------------------------------------------------- | | App scaffolding | Application | Manages renderer + stage + ticker | | Group/layer objects | Container | Only class that accepts children | | Display an image/texture | Sprite | Fastest renderable; use spritesheets | | Draw shapes programmatically | Graphics | v8: shape→fill order; shares GraphicsContext | | Canvas-rendered text | Text | Flexible styling; expensive if updated every frame | | High-perf static/dynamic text | BitmapText | GPU-batched; best for score counters, labels | | HTML/CSS styled text | HTMLText | Rich formatting; slower than canvas text | | 10k+ particles | ParticleContainer + Particle | Flat list, no children, requires boundsArea | | Custom rendering batch | Mesh | Full shader control | | 9-slice UI panel | NineSliceSprite | Renamed from NineSlicePlane in v8 | | Tiling background | TilingSprite | Repeating texture | | Load assets | Assets (static) | Global singleton, cached, async | | GPU-optimized sub-tree | Container with isRenderGroup: true | Transforms applied on GPU |
Quick Start
import { Application, Assets, Sprite } from 'pixi.js';
// 1. Create and initialize the app (MUST await)
const app = new Application();
await app.init({
width: 800,
height: 600,
backgroundColor: 0x1099bb,
resolution: window.devicePixelRatio,
autoDensity: true
});
// 2. Add canvas to the DOM
document.body.appendChild(app.canvas);
// 3. Load assets via Assets (returns cached textures on repeat calls)
const texture = await Assets.load('bunny.png');
// 4. Create a sprite and add to stage
const bunny = new Sprite(texture);
bunny.anchor.set(0.5); // center anchor
bunny.position.set(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(bunny);
// 5. Animate with ticker
app.ticker.add((ticker) => {
bunny.rotation += 0.05 * ticker.deltaTime;
});
ApplicationOptions (key fields)
| Option | Type | Default | Description | | ------------------------------ | --------------------------------- | ---------- | ---------------------------------------- | | width | number | 800 | Canvas width in pixels | | height | number | 600 | Canvas height in pixels | | backgroundColor | ColorSource | 0x000000 | Background fill color | | backgroundAlpha | number | 1 | Background alpha (0 = transparent) | | antialias | boolean | false | Enable MSAA antialiasing | | resolution | number | 1 | Device pixel ratio | | autoDensity | boolean | false | Auto-adjust CSS size to match resolution | | preference | 'webgl' \| 'webgpu' \| 'canvas' | 'webgl' | Renderer preference | | resizeTo | Window \| HTMLElement | — | Auto-resize to element | | autoStart | boolean | true | Start ticker automatically | | sharedTicker | boolean | false | Use shared global ticker | | manageImports | boolean | true | Auto-import default extensions | | textureGCActive | boolean | true | Enable texture garbage collection | | textureGCMaxIdle | number | 3600 | Frames before texture GC | | roundPixels | boolean | false | Force pixel-rounding on renderer | | failIfMajorPerformanceCaveat | boolean | false | Fail on GPU denylist |
Quick Reference
Container (base class for all scene objects)
// Transform
container.x = 100; container.y = 200;
container.position.set(100, 200);
container.scale.set(2); // uniform scale
container.rotation = Math.PI / 4; // radians
container.angle = 45; // degrees (alias)
container.pivot.set(50, 50); // rotation origin (local coords)
container.origin.set(50, 50); // rotate around point without offset
// Appearance
container.alpha = 0.5;
container.visible = false; // skips draw + transform
container.renderable = false; // skips draw, keeps transform
container.tint = 0xff0000; // red tint
container.blendMode = 'add';
// Children
container.addChild(child);
container.removeChild(child);
container.addChildAt(child, 0);
container.setChildIndex(child, 2);
container.sortableChildren = true;
child.zIndex = 10;
// Bounds
const bounds = container.getBounds().rectangle; // returns Bounds, use .rectangle
container.boundsArea = new Rectangle(0, 0, 400, 400); // optimization
// Culling
container.cullable = true;
container.cullArea = new Rectangle(0, 0, 400, 400);
container.cullableChildren = false;
// Events
container.on('pointerdown', (e) => { ... });
container.eventMode = 'static'; // 'none' | 'passive' | 'auto' | 'static' | 'dynamic'
container.interactiveChildren = false; // skip hit-testing children
// Utility
const globalPos = container.toGlobal(new Point(0, 0));
const localPos = container.toLocal(new Point(100, 100));
container.label = 'myContainer'; // was .name in v7
container.onRender = () => { /* per-frame logic */ }; // replaces updateTransform
// Performance
const rg = new Container({ isRenderGroup: true }); // GPU-side transforms
container.cacheAsTexture(true); // was cacheAsBitmap in v7
Sprite
// Creation
const sprite = new Sprite(texture);
const sprite = Sprite.from('image.png'); // requires texture already loaded via Assets
const sprite = new Sprite({ texture, anchor: 0.5, roundPixels: true });
// Anchor (0=top-left, 0.5=center, 1=bottom-right)
sprite.anchor.set(0.5);
sprite.anchor.set(0.5, 0);
// Size
sprite.width = 100;
sprite.height = 200;
// Texture swap
sprite.texture = newTexture;
// After manual UV modification, force update:
sprite.onViewUpdate();
Graphics
const g = new Graphics();
// v8 pattern: build shape THEN apply fill/stroke
g.rect(x, y, w, h).fill(0xff0000);
g.rect(x, y, w, h).fill({ color: 0xff0000, alpha: 0.5 });
g.rect(x, y, w, h).fill({ texture: myTexture }).stroke({ width: 2, color: 'white' });
// Shapes
g.circle(cx, cy, radius).fill(0x00ff00);
g.ellipse(cx, cy, rx, ry).fill(color);
g.roundRect(x, y, w, h, radius).fill(color);
g.poly([x1, y1, x2, y2, x3, y3]).fill(color);
g.moveTo(x, y).lineTo(x2, y2).stroke({ width: 2, color: 0xffffff });
// Holes (cut = hollow out previous shape)
g.rect(0, 0, 100, 100).fill(0x00ff00).circle(50, 50, 20).cut();
// Shared context (draw once, render many)
const ctx = new GraphicsContext().rect(0, 0, 50, 50).fill(0xff0000);
const g1 = new Graphics(ctx);
const g2 = new Graphics(ctx); // same GPU data, different transforms
// As mask
sprite.mask = g;
Text / BitmapText / HTMLText
// Canvas text — flexible, expensive to update
const text = new Text({
text: 'Hello!',
style: {
fontFamily: 'Arial',
fontSize: 24,
fill: 0xff1010,
align: 'center',
wordWrap: true,
wordWrapWidth: 200,
stroke: { color: '#4a1850', width: 5 },
dropShadow: { color: '#000000', blur: 4, distance: 6, angle: Math.PI / 6 }
},
anchor: 0.5
});
// BitmapText — best for score counters, frequently updated labels
const bmpText = new BitmapText({ text: '0', style: { fontFamily: 'Arial', fontSize: 24 } });
// HTMLText — rich HTML markup support
const htmlText = new HTMLText({ text: 'Bold and italic' });
// Constructor change from v7:
// OLD: new Text('Hello', { fontSize: 24 })
// NEW: new Text({ text: 'Hello', style: { fontSize: 24 } })
Assets
// Load single asset
const texture = await Assets.load('sprite.png');
// Load multiple
const assets = await Assets.load(['a.png', 'b.png']);
// With alias
Assets.add({ alias: 'hero', src: 'hero.{webp,png}' });
const texture = await Assets.load('hero');
// Bundles
await Assets.init({
manifest: {
bundles: [{ name: 'game', assets: [{ alias: 'bg', src: 'bg.png' }] }]
}
});
await Assets.loadBundle('game');
// Background preload
Assets.backgroundLoad(['next-level.png']);
// Unload
await Assets.unload('sprite.png');
texture.source.unload(); // manual GPU unload
Ticker
// App ticker (runs automatically)
app.ticker.add((ticker) => {
sprite.rotation += 0.05 * ticker.deltaTime; // deltaTime = frame delta in ticks
});
// Shared global ticker
import { Ticker } from 'pixi.js';
Ticker.shared.add((ticker) => { ... });
Ticker.shared.remove(myFn);
// Manual control
app.ticker.stop();
app.ticker.start();
Destroy / Cleanup
// Sprite only (preserves texture)
sprite.destroy();
// Sprite + texture
sprite.destroy({ texture: true, textureSource: true });
// Container tree
container.destroy({ children: true });
// Full app teardown
app.destroy({ removeView: true }, { children: true, texture: true });
// Unload via Assets (removes from cache + GPU)
await Assets.unload('sprite.png');
References
- [Core Classes](references/core-classes.md) — Container, Sprite, Graphics, Text details
- [Configuration](references/configuration.md) — all Options interfaces
- [Migration v7→v8](references/migration-v8.md) — breaking changes
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: pradeepmouli
- Source: pradeepmouli/skillit
- License: MIT
- Homepage: https://pradeepmouli.github.io/skillit/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.