Phaser 3 Tricks: Make Circle Image.

Hi, in this story I will share how to use masking responsively. You can use a mask in your container without worries, that mask can’t be offset. Let’s do it.
export default class ImageCircle extends Phaser.GameObjects.Container {image: Phaser.GameObjects.Image;
circle: Phaser.GameObjects.Graphics;
radius: number; constructor(scene: Phaser.Scene, x: number, y: number, image: Phaser.GameObjects.Image | string, frame?: string | number, radius?: number) { super(scene, x, y); // TODO: set image into this variable }}
That class is a container that has an image and a circle mask. You can use that image as an image game object or a string. The parameter radius is the radius of the circle mask, you can set it manually or automatically by the image shortest size. Add the bellow code into the constructor function:
// set image as string
if (typeof image === 'string') {
this.image = new Phaser.GameObjects.Image(scene, 0, 0, image, frame);
} else {
this.image = image;
}// get radius by radius param or half of shortest image size
this.radius = radius || Math.min(this.image.width, this.image.height) / 2;// add graphics into the scene and fill it with circle
// importance to set circle position to the (x, y)first
this.circle = scene.add.graphics().setPosition(x, y).fillCircle(0, 0, this.radius);// add image into the child of container
this.add(this.image);// set mask image by the circle graphics
this.image.setMask(this.circle.createGeometryMask());
Then we go to the main function the updateMaskTransform. That function is update circle mask position and scale by the image transform in the world.
updateMaskTransform() { const transfrom = this.image.getWorldTransformMatrix(); this.circle
.setPosition(transfrom.getX(0, 0), transfrom.getY(0, 0))
.setScale(transfrom.scaleX, transfrom.scaleY); return this;
}
You must call that function when resize or move your image circle. You can use the preUpdate method in the image circle class to hack the problem 😂.
Thanks for reading, and if there’s something you’d like to see in future posts, let me know!
Full Code
export default class ImageCircle extends Phaser.GameObjects.Container { image: Phaser.GameObjects.Image;
circle: Phaser.GameObjects.Graphics;
radius: number; constructor(scene: Phaser.Scene, x: number, y: number, image: Phaser.GameObjects.Image | string, frame?: string | number, radius?: number) { super(scene, x, y); if (typeof image === 'string') {
this.image = new Phaser.GameObjects.Image(scene, 0, 0, image, frame);
} else {
this.image = image;
} // get radius by radius param or half of shortest image size
this.radius = radius || Math.min(this.image.width, this.image.height) / 2; // add graphics into the scene and fill it with circle
// importance to set circle position to the (x, y)first
this.circle = scene.add.graphics().setPosition(x, y).fillCircle(0, 0, this.radius); // add image into the child of container
this.add(this.image); // set mask image by the circle graphics
this.image.setMask(this.circle.createGeometryMask());
} updateMaskTransform() { const transfrom = this.image.getWorldTransformMatrix(); this.circle.setPosition(transfrom.getX(0, 0), transfrom.getY(0, 0)).setScale(transfrom.scaleX, transfrom.scaleY); }}
Bonuses:
Set background-color
setBackground(color: number, alpha = 0) {
this.circle.clear()
.fillStyle(color, alpha)
.fillCircle(0, 0, this.radius); this.updateMaskTransform();
return this;
}
Minimalize Phaser Template: https://github.com/ArifZx/phaser3-typescript-webpack-externals-template
