MCPInstall

groups-and-containers

Use this skill when using Groups or Containers in Phaser 4. Covers organizing game objects, object pooling, batch operations, and nested transforms with Containers. Triggers on: Group, Container, object pool, getFirstDead, children.

Installs
798
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/phaserjs/phaser --skill groups-and-containers
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads groups-and-containers automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Groups and Containers

Logical grouping (Group), visual grouping with transform inheritance (Container), render-layer grouping (Layer), object pooling, and when to use each in Phaser 4.

Key source paths: src/gameobjects/group/, src/gameobjects/container/, src/gameobjects/layer/ Related skills: ../sprites-and-images/SKILL.md, ../physics-arcade/SKILL.md

Quick Start

// In a Scene's create() method:

// --- Group: logical collection, no transform, great for pooling ---
const enemies = this.add.group();
enemies.create(100, 200, 'enemy');       // creates Sprite at (100,200)
enemies.create(300, 200, 'enemy');

// --- Container: visual parent with inherited transform ---
const hud = this.add.container(10, 10);
const icon = this.add.image(0, 0, 'heart');
const label = this.add.text(20, 0, 'x3');
hud.add([icon, label]);                  // children move/scale/rotate with hud

// --- Layer: render-ordering bucket, no position/scale ---
const bgLayer = this.add.layer();
const fgLayer = this.add.layer();
bgLayer.add(this.add.image(400, 300, 'sky'));
fgLayer.add(this.add.sprite(400, 300, 'player'));

Core Concepts

Group vs Container vs Layer

FeatureGroupContainerLayer
PurposeLogical collection / poolVisual parent with transformRender-order bucket
On display listNo (children are)Yes (renders children)Yes (renders children)
Position/rotation/scaleNoYes (children inherit)No
Children storagechildren (Set)list (Array)List (Structs.List)
PhysicsVia physics.add.group()Limited (offsets if not at 0,0)No
InputNo (children can)Yes (needs hit area shape)No
Object poolingYes (getFirstDead, kill)NoNo
MasksNoYes (not per-child in Canvas)Yes
Alpha/blend/visibleNo (batch via setVisible)YesYes
NestingN/AContainer in ContainerCannot go in Container
ExtendsEventEmitterGameObjectList
Factorythis.add.group()this.add.container(x, y)this.add.layer()

When to Use Each

Group: Managing collections of similar objects (enemies, bullets, coins), object pooling with active/inactive lifecycle, physics group collisions. No shared visual transform. Members can belong to multiple Groups simultaneously.

Container: Children inherit position, rotation, scale, alpha. Composite UI elements (health bars, inventory slots), moving/rotating clusters as one unit, nested transforms. By default exclusive -- a child can only belong to one Container (use setExclusive(false) to override).

Layer: Controlling render order of object batches, applying shared alpha/blend/mask. No position/scale/rotation. Lightweight render bucketing.

Container vs Group at a Glance

  • Container has position, rotation, scale, alpha -- Group does not. If you need children to move/rotate as a unit, use Container.
  • Container is exclusive by default -- adding a child removes it from its previous Container. Group is non-exclusive; a game object can be in many Groups.
  • Container is on the display list -- it renders its children. Group is not on the display list; its children render individually on the Scene.
  • Group supports object pooling -- getFirstDead, kill, killAndHide. Container does not.
  • Container has performance cost -- each child requires matrix math per frame. Deeper nesting = more cost. Prefer Group or Layer when transforms are not needed.

Common Patterns

Creating and Populating Groups

// Empty group, add existing objects
const gems = this.add.group();
gems.add(existingSprite);
gems.addMultiple([sprite1, sprite2, sprite3]);

// Group with config -- creates children automatically
const coins = this.add.group({
    classType: Phaser.GameObjects.Sprite,
    key: 'coin',
    quantity: 10,           // overrides frameQuantity
    setXY: { x: 50, y: 300, stepX: 60 },
    setScale: { x: 0.5, y: 0.5 }
});

// Custom class type with pool limit
const bullets = this.add.group({
    classType: Bullet,       // must accept (scene, x, y, key, frame)
    maxSize: 30,
    defaultKey: 'bullet',
    runChildUpdate: true     // calls child.update() each frame
});

Object Pooling with getFirstDead

The core pooling pattern: deactivate objects instead of destroying them, then reuse inactive ones.

// Setup pool
const bullets = this.add.group({
    classType: Phaser.GameObjects.Sprite,
    defaultKey: 'bullet',
    maxSize: 30
});

// Fire a bullet -- get() finds first inactive member or creates one
function fireBullet(x, y) {
    const bullet = bullets.get(x, y);

    if (bullet) {
        bullet.setActive(true);
        bullet.setVisible(true);
        bullet.body.velocity.y = -300;   // if physics enabled
    }
}

// Deactivate when off-screen or on hit
function killBullet(bullet) {
    bullets.killAndHide(bullet);         // sets active=false, visible=false
    // If using physics, also reset the body:
    // bullet.body.stop();
}

// Alternative: manual getFirst
const inactive = bullets.getFirst(false);     // first where active===false
const active = bullets.getFirstAlive();       // first where active===true
const dead = bullets.getFirstDead(true, x, y); // first inactive, create if null

Pool helper methods on Group:

MethodDescription
get(x, y, key, frame)Shortcut: getFirst(false, true, ...) -- finds inactive or creates
getFirst(state, createIfNull, x, y, key, frame)First member matching active state
getFirstAlive(createIfNull, x, y, key, frame)First member where active===true
getFirstDead(createIfNull, x, y, key, frame)First member where active===false
getLast(state, createIfNull, x, y, key, frame)Like getFirst but searches back-to-front
kill(gameObject)Sets active=false on a member
killAndHide(gameObject)Sets active=false and visible=false
countActive(value)Count members where active===value (default true)
getTotalUsed()Count of active members
getTotalFree()maxSize - active count (remaining pool capacity)
isFull()True if children.size >= maxSize

Physics Groups

Physics groups extend Group with automatic body assignment. See ../physics-arcade/SKILL.md for full details.

// Arcade Physics group -- every member gets a dynamic body
const enemies = this.physics.add.group({
    key: 'enemy',
    quantity: 5,
    setXY: { x: 100, y: 100, stepX: 80 }
});

// Static physics group -- immovable bodies
const platforms = this.physics.add.staticGroup();
platforms.create(400, 568, 'ground');

// Collide physics groups with each other
this.physics.add.collider(player, platforms);
this.physics.add.overlap(bullets, enemies, onHit);

Containers with Nested Transforms

// HUD that follows camera
const hud = this.add.container(10, 10);
hud.setScrollFactor(0);     // pinned to camera

const healthBar = this.add.rectangle(0, 0, 200, 20, 0x00ff00);
const healthText = this.add.text(210, -5, '100 HP');
hud.add([healthBar, healthText]);

// Move everything at once
hud.setPosition(50, 50);

// Scale and rotate propagate to children
hud.setScale(1.5);
hud.setRotation(0.1);

// Alpha affects all children
hud.setAlpha(0.8);

// Nested containers
const inventory = this.add.container(300, 500);
for (let i = 0; i < 5; i++) {
    const slot = this.add.container(i * 55, 0);
    slot.add([
        this.add.rectangle(0, 0, 48, 48, 0x333333),
        this.add.image(0, 0, `item-${i}`)
    ]);
    inventory.add(slot);    // Container inside Container
}

Key Container methods:

MethodDescription
add(child) / addAt(child, index)Add Game Object(s); removes from display list
remove(child, destroyChild)Remove; optionally destroy
getAt(index) / getIndex(child)Access by index
getByName(name) / getFirst(prop, val)Query children
getAll(prop, val) / count(prop, val)Filtered access and counting
sort(property) / swap(a, b) / moveTo(child, idx)Ordering
each(cb, ctx) / iterate(cb, ctx)Iteration (iterate passes index)
setScrollFactor(x, y, updateChildren)Pass true to also apply to children
getBounds(output)Bounding rect of all children
pointToContainer(source, output)World point to local space
setExclusive(value)When false, children can exist in multiple places
replace(oldChild, newChild)Swap one child for another
setSize(width, height)Set hit area size (required for input)
lengthRead-only child count

Layers for Render Ordering

const bgLayer = this.add.layer();
const entityLayer = this.add.layer();
const uiLayer = this.add.layer();

// Add objects -- they render in layer order, then by depth within layer
bgLayer.add(this.add.image(400, 300, 'sky'));
entityLayer.add(player);
entityLayer.add(enemy);
uiLayer.add(scoreText);

// Control depth of layers themselves
bgLayer.setDepth(0);
entityLayer.setDepth(1);
uiLayer.setDepth(2);

// Children set depth within their layer
enemy.setDepth(5);   // relative to entityLayer, not the Scene

// Apply shared effects to entire layer
entityLayer.setAlpha(0.5);
entityLayer.setVisible(false);
entityLayer.setBlendMode(Phaser.BlendModes.ADD);

Bulk Creation with createMultiple

// createMultiple accepts a GroupCreateConfig or array of them
const coins = this.add.group();

coins.createMultiple({
    key: 'coin',
    quantity: 20,
    setXY: { x: 50, y: 100, stepX: 40, stepY: 0 },
    setScale: { x: 0.5, y: 0.5 },
    setRotation: { value: 0, step: 0.1 },   // each rotated 0.1 more than previous
    setAlpha: { value: 1 },
    setOrigin: { x: 0.5, y: 0.5 },
    setDepth: { value: 5 },
    gridAlign: {
        width: 5,
        height: 4,
        cellWidth: 48,
        cellHeight: 48,
        x: 100,
        y: 200
    }
});

// Multiple configs at once (creates two different sets)
coins.createMultiple([
    { key: 'gold-coin', quantity: 10, setXY: { x: 50, y: 100, stepX: 30 } },
    { key: 'silver-coin', quantity: 10, setXY: { x: 50, y: 200, stepX: 30 } }
]);

Iterating and Batch Operations on Groups

const enemies = this.add.group();

// Get all children as array
const all = enemies.getChildren();
const active = enemies.getMatching('active', true);

// Batch property operations
enemies.setXY(200, 300);
enemies.incX(5);                    // add 5 to each member's x
enemies.setVisible(false);
enemies.propertyValueSet('tintTopLeft', 0xff0000);
enemies.playAnimation('walk');

// Stepping: apply incremental values across members
enemies.setX(100, 50);             // first at x=100, next at 150, then 200...
enemies.setY(200, 30);             // first at y=200, next at 230, then 260...
enemies.setXY(100, 200, 50, 30);   // combined X and Y stepping
enemies.incXY(10, 5);              // add 10 to each x, 5 to each y
enemies.angle(0, 15);              // first at 0 deg, next at 15, then 30...
enemies.setAlpha(1, -0.1);         // first at 1.0, next at 0.9, then 0.8...
enemies.setScale(1, 0, 0.1, 0);   // scaleX: 1.0, 1.1, 1.2... (stepX=0.1)
enemies.setDepth(0, 1);            // depth 0, 1, 2, 3...
enemies.setOrigin(0.5);
enemies.setBlendMode(Phaser.BlendModes.ADD);
enemies.setTint(0xff0000);
enemies.shuffle();                  // randomize order in the group

API Quick Reference

Group (Phaser.GameObjects.Group)

Factory:  this.add.group(children?, config?)

Config types:
  GroupConfig       -- classType, name, active, maxSize, defaultKey, defaultFrame,
                       runChildUpdate, createCallback, removeCallback
  GroupCreateConfig -- key (required), classType, frame, quantity, visible, active,
                       repeat, yoyo, frameQuantity, max, setXY, setRotation,
                       setScale, setOrigin, setAlpha, setDepth, setScrollFactor,
                       hitArea, gridAlign

Key members:  children (Set), classType, maxSize, defaultKey, defaultFrame,
              active, runChildUpdate
Lifecycle:    create, createMultiple, add, addMultiple, remove, clear, destroy
Queries:      getFirst, getFirstAlive, getFirstDead, getLast, get, getChildren,
              getLength, getMatching, contains, countActive, getTotalUsed,
              getTotalFree, isFull
Pool:         get, getFirstDead, kill, killAndHide
Bulk ops:     setX/Y/XY, incX/Y/XY, setAlpha, setVisible, toggleVisible,
              playAnimation, propertyValueSet, propertyValueInc, setOrigin,
              setDepth, shuffle, setBlendMode, setTint

Container (Phaser.GameObjects.Container)

Factory:  this.add.container(x?, y?, children?)

Extends:  GameObject
Mixins:   AlphaSingle, BlendMode, ComputedSize, Depth, Mask, Transform, Visible

Key members:  list (Array), exclusive, maxSize, scrollFactorX/Y
Children:     add, addAt, remove, removeAt, removeBetween, removeAll
Queries:      getAt, getIndex, getByName, getFirst, getAll, getRandom, count
Ordering:     sort, swap, moveTo, moveUp, moveDown, sendToBack, bringToTop,
              moveAbove, moveBelow, reverse
Transform:    pointToContainer, getBounds, getBoundsTransformMatrix
Iteration:    each(cb, ctx), iterate(cb, ctx, ...args)
Config:       setExclusive, setScrollFactor(x, y, updateChildren)
Property:     length (read-only child count)

Layer (Phaser.GameObjects.Layer)

Factory:  this.add.layer(children?)

Extends:  Phaser.Structs.List
Mixins:   AlphaSingle, BlendMode, Depth, Filters, Mask, RenderSteps, Visible

Key members:  scene, displayList, sortChildrenFlag
Children:     add, remove (inherited from List)
Settings:     setAlpha, setBlendMode, setDepth, setVisible, setMask, setName,
              setActive, setState, setData, getData

No position, rotation, scale, scroll factor, input, or physics.
Cannot be added to a Container. Containers can be added to Layers.

Gotchas

  1. Group is NOT on the display list. Its children appear on the Scene display list individually. Moving a Group does nothing visually -- use Container for that.

  2. Container has performance overhead. Every child requires extra matrix math per frame. Deep nesting multiplies this. Avoid Containers when a Group or Layer suffices.

  3. Container origin is always 0,0. The transform point cannot be changed. Position children relative to (0,0).

  4. Container children lose Scene-level depth control. A child's depth only orders within the Container. The Container's own depth positions it in the Scene.

  5. Physics + Container is problematic. If a Container is not at (0,0), physics bodies on children will be offset. Avoid physics bodies on Container children.

  6. Container children cannot be individually masked in Canvas rendering. Only the Container itself can have a mask. Masks do not stack for nested Containers. Masks do stack in WebGL rendering.

  7. Group.get() vs Group.getFirst() differ. get(x, y) is shorthand for getFirst(false, true, x, y) -- finds first inactive member and creates if none found. getFirst(state) defaults to active===false without auto-creating.

  8. Layer cannot go inside a Container. Containers can be added to Layers, but not the reverse.

  9. Group children Set is unordered. No index-based access. Use getChildren() to get an array snapshot.

  10. killAndHide does not remove from the group. It only sets active=false and visible=false. The object stays in the group for reuse.

  11. Container.setScrollFactor does not auto-propagate. Pass true as the third argument to also update children: container.setScrollFactor(0, 0, true).

  12. Group.create() adds to the Scene display list. But group.add() does NOT unless you pass true as the second argument.

  13. Container needs setSize() for input. Containers have no implicit size. You must call container.setSize(width, height) before setInteractive() will work with a hit area.

Source File Map

FileDescription
src/gameobjects/group/Group.jsGroup class -- pooling, create, getFirst*, kill, batch ops
src/gameobjects/group/GroupFactory.jsthis.add.group() factory registration
src/gameobjects/group/typedefs/GroupConfig.jsGroupConfig typedef (classType, maxSize, callbacks)
src/gameobjects/group/typedefs/GroupCreateConfig.jsGroupCreateConfig typedef (key, quantity, setXY, etc.)
src/gameobjects/container/Container.jsContainer class -- list management, nested transforms
src/gameobjects/container/ContainerFactory.jsthis.add.container() factory registration
src/gameobjects/container/ContainerRender.jsContainer WebGL/Canvas render functions
src/gameobjects/layer/Layer.jsLayer class -- display list bucket with alpha/blend/mask
src/gameobjects/layer/LayerFactory.jsthis.add.layer() factory registration
src/gameobjects/layer/LayerRender.jsLayer WebGL/Canvas render functions
src/physics/arcade/ArcadePhysics.jsthis.physics.add.group() / staticGroup()

FAQ

What does the groups-and-containers skill do?

Use this skill when using Groups or Containers in Phaser 4. Covers organizing game objects, object pooling, batch operations, and nested transforms with Containers. Triggers on: Group, Container, object pool, getFirstDead, children.

How do I install groups-and-containers?

Run npx skills add https://github.com/phaserjs/phaser --skill groups-and-containers in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/groups-and-containers/ (personal) or .claude/skills/groups-and-containers/ (project).

Which AI agents can use groups-and-containers?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is groups-and-containers safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains groups-and-containers?

It is published by phaserjs in phaserjs/phaser. It has 798 recorded installs.

More from phaserjs/phaser

View all →

game-setup-and-config

phaserjs/phaser

Use this skill when creating a new Phaser 4 game instance or configuring GameConfig options. Covers renderer selection, canvas setup, scaling, pixel art, FPS settings, boot sequence, and all config sub-objects. Triggers on: new Phaser.Game, GameConfig, game setup, renderer, pixel art, FPS.

Media & Creative1.2K installs

sprites-and-images

phaserjs/phaser

Use this skill when creating Sprites or Images in Phaser 4. Covers factory methods, texture/frame selection, position, scale, rotation, tint, flip, alpha, origin, depth, and the component mixin system. Triggers on: Sprite, Image, this.add.sprite, this.add.image, texture, setTint, setAlpha.

Media & Creative1.1K installs

animations

phaserjs/phaser

Use this skill when creating or controlling sprite animations in Phaser 4. Covers spritesheets, atlases, AnimationManager, AnimationState, play/stop/chain, frame callbacks, and animation events. Triggers on: sprite animation, spritesheet, play animation, animation frames.

Frontend & Design1.1K installs

tilemaps

phaserjs/phaser

Use this skill when working with tilemaps in Phaser 4. Covers loading Tiled JSON maps, creating tilemap layers, tile collision, dynamic tiles, tile properties, and tilemap camera culling. Triggers on: Tilemap, Tiled, tilemap layer, tile collision, tile properties.

972 installs

v4-new-features

phaserjs/phaser

Use this skill when learning about new features, game objects, components, and rendering capabilities added in Phaser 4. Covers Filters, RenderNodes, CaptureFrame, Gradient, Noise, SpriteGPULayer, TilemapGPULayer, Lighting component, RenderSteps, and new tint modes. Triggers on: new in v4, Phaser 4 features, RenderNode, SpriteGPULayer, CaptureFrame, Gradient game object, Noise game object, new tint modes. For migrating v3 code to v4, see the v3-to-v4-migration skill instead.

Media & Creative965 installs

scenes

phaserjs/phaser

Use this skill when working with Phaser 4 scenes. Covers scene lifecycle methods, scene transitions, parallel scenes, scene communication, sleeping, pausing, restarting, and the SceneManager. Triggers on: Scene, scene lifecycle, preload, create, update, scene transition, SceneManager.

956 installs

Popular media & creative skills

View category →

hyperframes

heygen-com/hyperframes

Read first to make, edit, animate or render any video with HyperFrames (HTML rendered to video), including launch films, explainers, music videos, charts, maps, vertical clips, title cards, captions and overlays. Holds the render contract, the work loop and what each kind of video needs.

Media & Creative1.2M installs

media-use

heygen-com/hyperframes

Get or make any media for a HyperFrames video - music, sound effects, images, icons, logos, voiceover, avatar and generated video, transcripts, cutouts, colour grades and looks - with HeyGen or free local tools, and mix placed audio. Also for footage that looks dark, flat or dull, or should be stylized or hidden.

Media & Creative1.1M installs

hyperframes-registry

heygen-com/hyperframes

About 450 ready-made HyperFrames blocks and components installed as editable source - transitions, overlays, titles, kinetic type, captions, charts, map overlays, 3D, camera moves. Use it before hand-building any named visual (CRT scanlines, glitch, film grain, a chart); also for hyperframes add and catalog.

Media & Creative1M installs

hyperframes-creative

heygen-com/hyperframes

Non-animation creative direction for HyperFrames videos. Use for design spec (frame.md / design.md) handling, palettes, typography, narration, beat planning, audio-reactive visuals, composition patterns, and brand / style decisions. For atomic motion patterns and scene blueprints, use hyperframes-animation.

Media & Creative916.5K installs

ai-video-generation

101-skills/superpowers

Generate AI videos with Google Veo, Seedance 2.0, HappyHorse, Wan, Grok and 40+ models via inference.sh CLI. Models: Veo 3.1, Veo 3, Seedance 2.0, HappyHorse 1.0, Wan 2.5, Grok Imagine Video, OmniHuman, Fabric, HunyuanVideo. Capabilities: text-to-video, image-to-video, reference-to-video, video editing, lipsync, avatar animation, video upscaling, foley sound. Use for: social media videos, marketing content, explainer videos, product demos, AI avatars. Triggers: video generation, ai video, text to video, image to video, veo, animate image, video from image, ai animation, video generator, generate video, t2v, i2v, ai video maker, create video with ai, runway alternative, pika alternative, sora alternative, kling alternative, seedance, happyhorse

Media & Creative881.5K installs

ai-image-generation

101-skills/superpowers

Generate AI images with GPT-Image-2, FLUX, Gemini, Grok, Seedream, Reve and 50+ models via inference.sh CLI. Models: GPT-Image-2, FLUX Dev LoRA, FLUX.2 Klein LoRA, Gemini 3 Pro Image, Grok Imagine, Seedream 4.5, Reve, ImagineArt. Capabilities: text-to-image, image-to-image, inpainting, LoRA, image editing, upscaling, text rendering. Use for: AI art, product mockups, concept art, social media graphics, marketing visuals, illustrations. Triggers: flux, image generation, ai image, text to image, stable diffusion, generate image, ai art, midjourney alternative, dall-e alternative, text2img, t2i, image generator, ai picture, create image with ai, generative ai, ai illustration, grok image, gemini image, gpt image, openai image, chatgpt image

Media & Creative880.3K installs