Phaser 3 Tricks: Make Circle Image.

Arif Budiman
3 min readMay 14, 2020

--

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

--

--