Masks in Phaser 4

In Phaser 4, Geometry Masks are for the Canvas Renderer only. The WebGL Renderer uses Mask Filters instead. Bitmap Masks are gone.

As with all Phaser 4 Filters:

  • The Canvas Renderer can’t create Mask Filters so trying to access them will error.
  • Cameras and Game Objects can have Mask Filters.
  • For Game Objects with width and height, Filters can be applied in an internal or external context. The internal context is the Game Object itself. The external context is usually similar to the global space of Phaser 3 Masks. A Camera’s internal and external contexts are identical.
  • Mask Filters can be stacked, so you can compose Masks from several Game Objects or Textures.

For Mask Filters in particular:

  • The Mask source can be a Game Object or a Texture.
    • A Texture Mask source is always positioned and stretched to fit its context.
    • A Game Object Mask source can be any renderable Game Object — there’s no Bitmap vs. Geometry distinction. The source can be positioned, rotated, scaled, etc.
    • A Game Object Mask source can be inside a Container, but you don’t need a Container to keep the source on its target — the internal context is that already.
  • The Mask can be inverted.
  • The Mask can be activated or deactivated.
  • The Mask can auto-update or not.

If you’re not interested in supporting Canvas, set the renderer to WebGL only and handle the no-WebGL condition once:

try {
  new Phaser.Game({ type: Phaser.WEBGL });
} catch (err) {
  alert('This game requires WebGL.');
}

As with other Filters, you enable filters for the Game Object and then create a Mask Filter on its internal or external list:

// Mask source:
const maskImage = this.make.image({ key: 'mask', add: false });

// Mask target:
const layer = this.add.layer();

layer.enableFilters();

// WebGL only:
const maskFilter = layer.filters.external.addMask(maskImage);

If you don’t need to access the Mask later, you can just do

// WebGL only:
layer.enableFilters().filters.external.addMask(image);

With the WebGL Renderer, Filters are always available on Cameras, so they need no enableFilters().

// WebGL only:
const maskFilter = this.cameras.main.filters.external.addMask(image);

With the Canvas Renderer, enableFilters() does nothing and accessing filters will error:

const maskFilter = layer.filters.external.addMask(image);
// -> TypeError: null is not an object (evaluating 'layer.filters.external')

For Masks from a Graphics source, you can support both renderers:

let geometryMask;
let maskFilter;

if (this.renderer.type === Phaser.WEBGL) {
  layer.enableFilters();

  maskFilter = layer.filters.external.addMask(graphics);
} else {
  geometryMask = graphics.createGeometryMask();

  layer.setMask(geometryMask);
}

Examples

Tests

https://codepen.io/samme/pen/xbxMwbr

3 Likes