Introduction
If you try to add a mask into a container or prefab and use it in your scene, you will recognize that it is not working as you expect. Because masks in phaser uses global coordinates. So if you need to keep your mask in the scene, synchronize their transforms with your container. In this post, I will give you a small tutorial about achieving that.
Prepare assets
For this example I've made two pictures, the Phaser's logo and simple rectangle mask. You can download it if you want.
Prepare prefab
In my case, the prefab extends the class Container, and contains two pictures which I will set from the game scene.
class Prefab extends Phaser.GameObjects.Container {
constructor(scene, x, y, spriteName, maskName) {
super(scene, x, y);
// add to the scene
scene.add.existing(this);
// add a logo sprite, attach to the scene
this.logoSprite = scene.add.sprite(0, 0, spriteName);
this.add(this.logoSprite);
// add a mask, set mask as invisible
this.maskSprite = scene.add.sprite(this.x, this.y, maskName);
this.maskSprite.setVisible(false);
// set the maskSprite as a mask to the logoSprite
this.mask = this.maskSprite.createBitmapMask();
this.logoSprite.setMask(this.mask);
}
}
Synchronize the mask position with the prefab
Now you need just add a function which will update the mask transform properties by the prefab's one.
// update the mask transform by postion of the prefab
updateMaskTransform() {
this.maskSprite.setPosition(this.x, this.y);
this.maskSprite.setScale(this.scaleX, this.scaleY);
this.maskSprite.setRotation(this.rotation);
}
Add the prefabs into the scene and try to animate
class Game extends Phaser.Scene {
constructor() {
super('Game');
}
// load images
preload(){
this.logo = this.load.image('logo', './img/logo.png')
this.mask = this.load.image('logo_mask', './img/logo_mask.png')
}
create() {
//initialize the prefabs, set position and pictures
const prefab1 = new Prefab(this, 300, 250, 'logo', 'logo_mask');
const prefab2 = new Prefab(this, 200, 600, 'logo', 'logo_mask');
// apply function for move, rotate and scale the prefabs
this.scalePrefabWithMask(prefab1);
this.rotatePrefabwithMask(prefab1);
this.scalePrefabWithMask(prefab2);
this.movePrefabwithMask(prefab2);
}
rotatePrefabwithMask(prefab) {
this.tweens.add({
targets: prefab,
angle: 360,
duration: 2000,
//update the mask's transform every frame
onUpdate: () => prefab.updateMaskTransform(),
repeat: -1,
});
}
scalePrefabWithMask(prefab) {
prefab.setScale(0.5);
//update the mask's transform after changing the prefab
prefab.updateMaskTransform();
}
movePrefabwithMask(prefab) {
this.tweens.add({
targets: prefab,
x: 400,
duration: 2000,
//update the mask's transform every frame
onUpdate: () => prefab.updateMaskTransform(),
yoyo: true,
repeat: -1,
});
}
}
If you done all steps right, you will see the same result.
That's all! I hope this guide will help you. You can see the full setup in the demo project.