-
Notifications
You must be signed in to change notification settings - Fork 4
Containers
Containers are display containers for other game objects.
When you add a child game object to a container, the child's x
and y
values don't change, but they become local coordinates, relative to the container's position. At render time the child is transformed into the container's space and drawn there. The local coordinates (0, 0) map onto the container's own x
and y
.
For display purposes, a container is a point, not a box. The local position (0, 0) is the transform origin for the children. You can treat (0, 0) as the "center" or "top-left" of the container by how you position the children, depending on the effect you want.
You can convert world coordinates into the container's coordinate space with its pointToContainer() method.
When you add a child game object to a container, the child is removed from any display list it belongs to (unless the container is not exclusive) and added to the container's own list. The child's parentContainer property holds the container.
If you remove a game object from a container, it's moved to the scene display list, so it will still be visible. If you want to remove the game object from the scene without destroying it, do also
gameObject.removeFromDisplayList().removeFromUpdateList();
Containers are dimensionless, but you can give them an artificial size for pointer input, physics, and camera culling:
container.setSize(100, 50);
For these purposes only, the container is treated like a rectangle with dimensions width
and height
and origin (0.5, 0.5). These dimensions don't influence child positioning at all. The width
and height
are initially zero.
You can calculate a container's bounds, the smallest rectangle containing all of its children:
const { left, right, top, bottom, width, height } = container.getBounds();
Game objects within a container aren't sorted by depth, so setting that will have no effect. Instead you use the container methods like bringToTop, sendToBack, and moveTo to reorder the children.
You can also sort the children:
container.sort('y');
Since containers render their children all at once, you can't mix depths of child game objects in different containers.
Display List (0)
├ Container (1)
│ ├ Sprite (2)
│ └ Sprite (3)
└ Container (4)
├ Sprite (5)
└ Sprite (6)
Containers aren't on the scene update list and don't update their children. Before Phaser v3.60.0, if you've instantiated an updatable game object and added it to a container, you also need to add it to the update list:
const sprite = new Phaser.GameObjects.Sprite(/*…*/);
sprite.addToUpdateList();
container.add(sprite);
When containers are given an exclusive value of false
, a game object can be added to several of them at once, and each container will render it.
Since game objects in non-exclusive containers are duplicated, they have some restrictions:
- They can't be used with pointer input
- They can't be given physics bodies
- They can't calculate global bounds
- They may work differently in camera culling
As containers are dimensionless, you should pass a hit area or call setSize() first.
Without setSize()
(the default), the container is treated as a point. The hit area's (x, y) is placed on the container's (x, y).
With setSize()
, the container is treated as a rectangle with origin (0.5, 0.5). The hit area's (x, y) is placed on the top-left of the rectangle, i.e., the container's (x - 0.5 * width, y - 0.5 * height).
Containers and children can be masked, but the mask source (game object) must be outside any container. (The mask will still apply, but it will appear in the wrong place.)
You can add a physics body to a container. You should call the container's setSize() first or use body.setSize() after.
Container children can also have physics bodies.
Remember that child coordinates are local. The constructor arguments x
y
are for the container itself.
If several game objects are positioned together only once but never moved thereafter, you don't need a container.
If you need to manage only alpha, blend modes, depth, masks, or visibility together (i.e. no transforms), you can use a layer instead.
If you need to translate (shift) a bunch of same-texture images, a blitter can be used instead.
You can scale, shift, and rotate a particle emitter without using a container at all.
For a scrolling/zooming "window", an extra camera may be a better choice.