Skip to main content
skill CX Codex

pixijs-scene-particle-container — Claude Code skill: what it does

Guides coding agents through PixiJS v8 ParticleContainer setup. Helps render thousands of lightweight sprites in a single draw call.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add pixijs/pixijs-skills --skill pixijs-scene-particle-container -a claude-code
Open on GitHub

What pixijs-scene-particle-container does

This skill guides AI assistants on using ParticleContainer and Particle instances in PixiJS v8. The specialized container is tailored for particle bursts and bullet patterns where you need numerous similar objects with minimal overhead. Every particle shares a single base texture source and uses a restricted transform set instead of standard container hierarchy.

ParticleContainer holds elements in its internal particleChildren array and rejects standard display children. You must call addParticle instead of addChild. Without configuring boundsArea, the container reports empty bounds (0, 0, 0, 0) for performance, causing immediate culling as invisible whenever culling is active.

The dynamicProperties object specifies which attributes re-upload to the GPU every frame. Only position defaults to true. Keeping rotation, UVs, and colors static preserves frame rates during heavy workloads.

What it helps with

  • render tens of thousands of sprites within a single draw call
  • configure dynamicProperties to upload only changing attributes to the GPU
  • set boundsArea to keep particle batches visible when culling is active
  • spawn bullet patterns using shared base textures

Example prompts for the agent

  • Show how to set up a ParticleContainer in PixiJS v8 for 10000 particles with a shared texture.
  • How do I configure dynamicProperties in ParticleContainer to animate position without updating rotation?
  • Why are particles disappearing from my PixiJS stage when culling is enabled?

How to install pixijs-scene-particle-container

1Skills CLI (Vercel)

npx skills add pixijs/pixijs-skills --skill pixijs-scene-particle-container -a claude-code

2Manually: put the files in place

~/.claude/skills/pixijs-scene-particle-container/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/pixijs-scene-particle-container/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about pixijs-scene-particle-container

How do I install pixijs-scene-particle-container in Claude Code?

Run npx skills add pixijs/pixijs-skills --skill pixijs-scene-particle-container -a claude-code in your project terminal.

What does pixijs-scene-particle-container do?

It provides the AI assistant with patterns and rules for ParticleContainer in PixiJS v8. This includes managing Particle structs, dynamicProperties, and avoiding common culling pitfalls.

Why is boundsArea required on a ParticleContainer?

For performance reasons, the container defaults to empty bounds (0, 0, 0, 0). Without boundsArea, the culling system treats the container as invisible and containsPoint checks always fail.

Source text

SKILL.md · MIT
---
name: pixijs-scene-particle-container
description: "Use this skill when rendering thousands of lightweight sprites in PixiJS v8. Covers ParticleContainer with Particle instances, addParticle/removeParticle, particleChildren array, dynamicProperties (vertex, position, rotation, uvs, color), boundsArea, roundPixels, update, inherited alpha/tint/blendMode from ancestors. Triggers on: ParticleContainer, Particle, IParticle, addParticle, particleChildren, dynamicProperties, boundsArea, particle effects, particle alpha, particle tint, fade particles, constructor options, ParticleContainerOptions, ParticleOptions."
license: MIT
---

`ParticleContainer` is a specialized container for rendering hundreds to tens of thousands of lightweight sprites in a single draw call. Use it for particle effects, bullet patterns, or any case where you need a large number of similar-looking objects with minimal per-object overhead. Particles share a single base texture and have a restricted transform set; they are not full `Container` children.

Assumes familiarity with `pixijs-scene-core-concepts`. `ParticleContainer` is a special leaf in a different sense: it contains `Particle` instances in its own `particleChildren` array and rejects normal PixiJS children. Use `addParticle`, not `addChild`, and wrap the whole `ParticleContainer` in a `Container` if you need to group it with other scene objects.

The Particle API is new in v8 but is stable for production use.

## Quick Start

```ts
const texture = await Assets.load("particle.png");

const container = new ParticleContainer({
  texture,
  boundsArea: new Rectangle(0, 0, app.screen.width, app.screen.height),
  dynamicProperties: {
    position: true,
    rotation: false,
    color: false,
  },
});

for (let i = 0; i < 10000; i++) {
  container.addParticle(
    new Particle({
      texture,
      x: Math.random() * app.screen.width,
      y: Math.random() * app.screen.height,
    }),
  );
}

app.stage.addChild(container);
```

**Related skills:** `pixijs-scene-core-concepts` (scene graph basics), `pixijs-scene-sprite` (when you need full features per object), `pixijs-assets` (shared textures, atlases), `pixijs-performance` (batching, texture optimization), `pixijs-scene-container` (wrap with other display objects).

## Constructor options

### ParticleContainerOptions

All `Container` options (`position`, `scale`, `tint`, `label`, `filters`, `zIndex`, etc.) are also valid here — see `skills/pixijs-scene-core-concepts/references/constructor-options.md`. Note that `children` is omitted: use `particles` instead.

| Option              | Type                 | Default                                                                        | Description                                                                                                                                                                     |
| ------------------- | -------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `texture`           | `Texture`            | `null`                                                                         | Shared base texture for all particles. If omitted, the container falls back to the texture of the first particle added; every particle must share the same base texture source. |
| `particles`         | `T[]`                | `[]`                                                                           | Initial array of `Particle` (or `IParticle`) instances. Equivalent to calling `addParticle` for each, but skips per-call view updates.                                          |
| `dynamicProperties` | `ParticleProperties` | `{ vertex: false, position: true, rotation: false, uvs: false, color: false }` | Flags for which particle attributes re-upload to the GPU every frame. Only `position` is dynamic by default; mark what you animate, leave the rest static for speed.            |
| `roundPixels`       | `boolean`            | `false`                                                                        | Rounds particle positions to the nearest pixel. Produces crisper rendering for pixel-art styles at the cost of smooth sub-pixel motion.                                         |
| `shader`            | `Shader`             | default particle shader                                                        | Replaces the default particle shader. The custom shader must declare `aPosition`, `aUV`, `aColor`, plus any dynamic-only attributes enabled via `dynamicProperties`.            |

`boundsArea` is inherited from `Container` but is effectively required on `ParticleContainer`: the container returns empty bounds `(0, 0, 0, 0)` by default for performance, so without `boundsArea` it is culled as invisible when culling is active and `containsPoint` always misses.

### ParticleOptions

`Particle` is a lightweight struct, not a `Container` subclass — none of the `ContainerOptions` fields apply. The full option list:

| Option     | Type          | Default    | Description                                                                                                                            |
| ---------- | ------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `texture`  | `Texture`     | —          | Required. Texture used to render this particle. All particles in the same `ParticleContainer` must share the same base texture source. |
| `x`        | `number`      | `0`        | X position in the container's local space.                                                                                             |
| `y`        | `number`      | `0`        | Y position in the container's local space.                                                                                             |
| `scaleX`   | `number`      | `1`        | Horizontal scale factor.                                                                                                               |
| `scaleY`   | `number`      | `1`        | Vertical scale factor.                                                                                                                 |
| `anchorX`  | `number`      | `0`        | Horizontal anchor in 0–1 range; `0` is left, `0.5` is center, `1` is right.                                                            |
| `anchorY`  | `number`      | `0`        | Vertical anchor in 0–1 range; `0` is top, `0.5` is center, `1` is bottom.                                                              |
| `rotation` | `number`      | `0`        | Rotation in radians.                                                                                                                   |
| `tint`     | `ColorSource` | `0xffffff` | Tint color as hex number or CSS color string. Combined with `alpha` into the internal `color` field.                                   |
| `alpha`    | `number`      | `1`        | Transparency (0–1). Values outside the range are clamped. Combined with `tint` into the internal `color` field.                        |

The constructor also accepts a bare `Texture` as its sole argument (`new Particle(texture)`), which is shorthand for `new Particle({ texture })` using the defaults above.

`Particle.defaultOptions` is a static object you can reassign to change defaults globally; see the "Particle creation" section below.

## Core Patterns

### Particle creation

```ts
const particle = new Particle({
  texture,
  x: 100,
  y: 200,
  scaleX: 0.5,
  scaleY: 0.5,
  anchorX: 0.5,
  anchorY: 0.5,
  rotation: Math.PI / 4,
  tint: 0xff0000,
  alpha: 0.8,
});

container.addParticle(particle);
```

`Particle` is a lightweight struct with flat numeric fields: `x`, `y`, `scaleX`, `scaleY`, `anchorX`, `anchorY`, `rotation`, `color`, `texture`. It also exposes `tint` (hex/CSS color) and `alpha` (0-1) as setters that combine into the internal `color` field. No transform hierarchy, no events, no filters.

You can pass a `Texture` directly as the sole argument: `new Particle(texture)`.

Override `Particle.defaultOptions` to change defaults globally:

```ts
Particle.defaultOptions = {
  ...Particle.defaultOptions,
  anchorX: 0.5,
  anchorY: 0.5,
};
```

### Pre-populating with the particles option

```ts
const particles = Array.from(
  { length: 10000 },
  () =>
    new Particle({
      texture,
      x: Math.random() * 800,
      y: Math.random() * 600,
    }),
);

const container = new ParticleContainer({
  texture,
  boundsArea: new Rectangle(0, 0, 800, 600),
  particles,
});
```

Passing `particles` in the constructor is equivalent to creating the container empty and calling `addParticle` for each one, but avoids per-call view updates.

### Dynamic vs static properties and update()

```ts
const container = new ParticleContainer({
  dynamicProperties: {
    rotation: true,
  },
});
```

`dynamicProperties` controls which particle attributes re-upload to the GPU every frame. The defaults on `ParticleContainer.defaultOptions.dynamicProperties` are:

```ts
{ vertex: false, position: true, rotation: false, uvs: false, color: false }
```

You only need to override the properties you are animating; the rest inherit the defaults (position dynamic, everything else static). Five properties in total:

- `vertex`: scale/anchor vertices
- `position`
- `rotation`
- `uvs`: texture coordinates (for frame-swapped particles)
- `color`: tint and alpha

Mark only what you animate; static properties are cheaper. If you change a static property at runtime, call `container.update()` to re-upload:

```ts
container.particleChildren.forEach((p) => {
  p.tint = 0x00ff00;
});
container.update();
```

### Batch operations on particleChildren

```ts
// Bulk add
const batch = [];
for (let i = 0; i < 5000; i++) {
  batch.push(
    new Particle({ texture, x: Math.random() * 800, y: Math.random() * 600 }),
  );
}
container.particleChildren.push(...batch);
container.update();

// Bulk remove
container.particleChildren.length = 0;
container.update();
```

`addParticle`, `addParticleAt`, `removeParticle`, `removeParticleAt`, and `removeParticles` all trigger view updates per call. For large batch operations, direct array manipulation plus a single `update()` is faster.

### Texture and shader options

`texture` in `ParticleContainerOptions` is optional. If omitted, the container falls back to the texture of the first particle added; every subsequent particle must share the same base texture source. Set it explicitly when you want to declare the atlas up front, or when the first particle might change mid-run:

```ts
const container = new ParticleContainer({ texture });
```

`shader` lets you replace the default particle shader with any `Shader` instance. The custom shader must declare the attributes the particle pipe uploads (`aPosition`, `aUV`, `aColor`, plus any dynamic-only attributes enabled via `dynamicProperties`). Use this for custom blending math, distance-field sprites, or non-standard effects:

```ts
const container = new ParticleContainer({ texture, shader: myCustomShader });
```

### Fading or tinting a whole particle system

```ts
const burst = new ParticleContainer({ texture, particles });
const layer = new Container();
layer.addChild(burst);

app.ticker.add(() => {
  layer.alpha -= 0.01; // fades every particle
});
burst.tint = 0x66ccff; // tints every particle
```

Container `alpha`, `tint`, and `blendMode` cascade into particles the same way they cascade into sprites, so you can fade or recolor an entire system without touching `particleChildren`.

### Limitations

`ParticleContainer` intentionally sacrifices features for speed:

- No filters, masks, or per-particle blend modes. Blend modes apply at the container level: set `blendMode` on the `ParticleContainer` or let it inherit from a parent `Container` (the default `"inherit"` resolves to the ancestor's blend mode, like `Sprite` and `Mesh`). The whole particle batch shares one blend mode. `alpha` and `tint` on the container or any ancestor multiply into every particle, on top of each particle's own `alpha`/`tint`.
- No nested children on particles.
- No automatic bounds calculation.
- All particles must share the same base texture source (atlases work; multiple unrelated textures do not).
- Custom shaders are supported via the `shader` option.

### Container method migration

`ParticleContainer` uses a separate child management API optimized for GPU buffer updates. The standard `Container` child methods throw when called on a `ParticleContainer`.

| Standard Container method    | ParticleContainer equivalent                        |
| ---------------------------- | --------------------------------------------------- |
| `addChild(child)`            | `addParticle(particle)`                             |
| `removeChild(child)`         | `removeParticle(particle)`                          |
| `addChildAt(child, index)`   | `addParticleAt(particle, index)`                    |
| `removeChildAt(index)`       | `removeParticleAt(index)`                           |
| `removeChildren(begin, end)` | `removeParticles(begin, end)`                       |
| `getChildAt(index)`          | Access `container.particleChildren[index]` directly |
| `swapChildren()`             | Not available                                       |
| `reparentChild()`            | Not available                                       |

## Common Mistakes

### [CRITICAL] Adding Sprites to ParticleContainer

Wrong:

```ts
const container = new ParticleContainer();
const sprite = new Sprite(texture);
container.addChild(sprite);
```

Correct:

```ts
const container = new ParticleContainer();
const particle = new Particle(texture);
container.addParticle(particle);
```

`ParticleContainer` does not accept `Sprite` children. `addChild` throws an error. Particles must be `Particle` instances (or any object implementing `IParticle`), added via `addParticle`. This is a complete rework from v7, where `ParticleContainer` accepted `Sprite` children.


### [HIGH] Not setting boundsArea on ParticleContainer

Wrong:

```ts
const container = new ParticleContainer();
// bounds is always (0, 0, 0, 0) — culling and hit testing fail
```

Correct:

```ts
const container = new ParticleContainer({
  boundsArea: new Rectangle(0, 0, 800, 600),
});
```

`ParticleContainer` returns empty bounds `(0, 0, 0, 0)` by default for performance. Without `boundsArea`, the container is culled as invisible when culling is active, and `containsPoint` always misses. Set `boundsArea` to the region your particles occupy.


### [HIGH] Using children instead of particleChildren

Wrong:

```ts
container.addParticle(new Particle(texture));
console.log(container.children.length); // 0
```

Correct:

```ts
container.addParticle(new Particle(texture));
console.log(container.particleChildren.length); // 1
```

Particles are stored in the `particleChildren` array, not `children`. The standard `Container.children` array is empty on a `ParticleContainer`. All particle enumeration, counting, and manipulation must use `particleChildren` plus the `*Particle` methods.


### [MEDIUM] Do not use ParticleContainer as a normal container

`ParticleContainer` contains particles, not display objects. If you need to group a particle system with a background sprite or UI overlay, wrap the `ParticleContainer` itself inside a plain `Container`:

```ts
const world = new Container();
world.addChild(backgroundSprite, particleContainer, uiLayer);
```


## API Reference

- [ParticleContainer](https://pixijs.download/release/docs/scene.ParticleContainer.html.md)
- [ParticleContainerOptions](https://pixijs.download/release/docs/scene.ParticleContainerOptions.html.md)
- [Particle](https://pixijs.download/release/docs/scene.Particle.html.md)
- [ParticleOptions](https://pixijs.download/release/docs/scene.ParticleOptions.html.md)
- [IParticle](https://pixijs.download/release/docs/scene.IParticle.html.md)
- [ParticleProperties](https://pixijs.download/release/docs/scene.ParticleProperties.html.md)

© pixijs · MIT · pixijs/pixijs-skills

Similar skills

Everything for Game dev and 3D: Unity, Unreal, Godot, Blender →

From the same set26

pixijs-scene-container Skill for PixiJS v8 scene graph operations: nesting children, handling transforms, zIndex sorting, and configuring Container options. CX Codex +1 5,900installs pixijs-scene-sprite This skill tells your agent how to draw images in PixiJS v8 with Sprite, AnimatedSprite, NineSliceSprite and TilingSprite. Useful when the project already runs PixiJS and you want working draw code fast. CX Codex +1 5,900installs pixijs-events A skill for pointer, mouse, touch and wheel input in PixiJS v8: eventMode values, FederatedEvent types, propagation and capture, hitArea, cursors, drag with globalpointermove. CX Codex +1 5,900installs pixijs-assets Provides PixiJS v8 resource management patterns for AI coding agents. Helps configure Assets.load, bundles, manifests, and explicit parsers for extension-less URLs. CX Codex +1 5,900installs pixijs-filters Guides PixiJS v8 visual effects through the filter pipeline. Use it for blur, colour adjustments, displacement, or custom shader effects. CX Codex +1 5,800installs pixijs-ticker A skill for per-frame logic in PixiJS v8: ticker callbacks, time units, priority ordering and frame rate capping. CX Codex +1 5,800installs pixijs-scene-text Teaches coding agents to render text in PixiJS v8 properly. Helps pick between bitmap, HTML, and canvas rendering without stalling frame updates. CX Codex +1 5,800installs pixijs-scene-core-concepts Explains how the PixiJS v8 scene graph fits together: containers, leaves, transforms and render order. Useful when your agent writes PixiJS code. CX Codex +1 5,900installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor