Game Object Masks

I’m not sure if this is a bug, but I use scene.add to create a container then give it a geometry mask and it works. I then scene.add a second container and add my first container to it.

It appears the mask I assigned my first container is no longer working. Neither containers have their positions changed during this creation phase, and both containers are positioned at [0, 0]. The mask is just a graphics object which I use fillRect to create the shape.

Does Phaser 3 support masks on nested containers, because it seems like that’s not the case?

Example:

this.container1 = this.add.container();
this.container1.add(this.add.image(100, 100, "Gems0001")); // this.make.image doesn't seem to work

const maskShape = this.make.graphics();
maskShape.fillStyle(0xffffff, 1);
maskShape.fillRect(100, 100, 50, 50);

this.container1.mask = new Phaser.Display.Masks.GeometryMask(this, maskShape);

this.container2 = this.add.container();
this.container2.add(this.container1);

This is also preventing object structure like:

const ProgressMeter = require("./ProgressMeter");

const AbilityMeter = new Phaser.Class({
    Extends: Phaser.GameObjects.Container,

    initialize:
        function AbilityMeter(scene, config) {
            const position = config.position || { x: 0, y: 0 };

            Phaser.GameObjects.Container.call(this, scene, position.x, position.y);
            this.config = config;

            this.progressMeter = new ProgressMeter(scene, config.progressMeter);
            this.add(this.progressMeter);

            const iconPos = config.icon.position || { x: 0, y: 0 };
            this.icon = scene.add.image(iconPos.x, iconPos.y, config.icon.key);
            this.add(this.icon);

            const labelPos = config.label.position || { x: 0, y: 0 };
            this.label = scene.add.bitmapText(labelPos.x, labelPos.y, config.label.font.key, config.id);
            this.add(this.label);
        }
});

module.exports = AbilityMeter;
const ProgressMeter = new Phaser.Class({
    Extends: Phaser.GameObjects.Container,

    initialize:
        function ProgressMeter(scene, config) {
            const position = config.position || { x: 0, y: 0 };

            Phaser.GameObjects.Container.call(this, scene, position.x, position.y);
            this.config = config;

            this.backing = scene.add.image(0, 0, config.backing.key);
            this.add(this.backing);

            this.fill = scene.add.image(0, 0, config.fill.key);
            this.fill.mask = this.createMask(this.fill.width * 0.5, this.fill.height); // test 50% full
            this.add(this.fill);
        },

    createMask:
        function(width, height) {
            const maskShape = this.scene.make.graphics();
            maskShape.fillStyle(0xffffff, 1);
            maskShape.fillRect(0, 0, width, height);
            return new Phaser.Display.Masks.GeometryMask(this.scene, maskShape);
        }
});

module.exports = ProgressMeter;

Containers can have masks set on them and can be used as a mask too. However, Container children cannot be masked. The masks do not ‘stack up’. Only a Container on the root of the display list will use its mask.

https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Container.html

2 Likes

That’s unfortunate, and a bit limiting. Thanks for pointing that out. Suppose I’ll have to rethink how my objects at structured :confused:

So please correct me if I am wrong, but Phaser does NOT support masking on nested elements in a container? How do we implement a dialog box with scrollable content without mask? I really do not wish to mix DOM with canvas…

Here are some UI plugins,
Scroll-able panel:

Yes, Phaser 3 does not currently support masks on nested objects within a container. This makes it very difficult, if not near impossible to structure and manage things like carousels, scroll bars, etc without using third party libraries.

EDIT: I seem to be mistaken.

It seems the functionality for nested masks has been added.