A reveal or scratch-off effect is where a top layer gets removed to reveal something hidden under it.
Like a scratch-off lottery ticket or a “Pick Your Bonus” mini-game.
There's more than one way to achieve this effect and we are going to look at one simple and performant approach using the Phaser 3 RenderTexture and ERASE blend mode.
How it Works
This approach relies on the image to be revealed being the same size and shape or smaller than the covering image. The top image has to completely hide the bottom image.

In this example, we refer to the top image as the “cover” and the bottom image as the “reveal”.
We will place them in the Scene so that the cover is always on top of the reveal. Then we will erase parts of the cover image by using a RenderTexture and another GameObject called a brush.
The brush will be an image of a radial gradient or a transparent image with one dot from a PhotoShop soft brush. The brush's alpha channel is respected so you can get different erase effects depending on the image used.
First, let's set up the scene.
|
|
For simplicity, we are using the same Phaser logo texture as the “cover” and “reveal” images. The difference will be a red tint added to the cover image so that we can tell them apart!
Notice that the cover image above is created with this.make.image but not added to the Scene. We will draw it into a RenderTexture instead.
Using a RenderTexture
A RenderTexture is a texture created at runtime that you can draw into. A normal Texture is like the phaser-logo.png that we load from the computer. It was created ahead of time in a graphics program.
This is different from a RenderTexture that does not exist until we run the game and create it in code.
A RenderTexture is empty until we draw something into it. Phaser lets us draw one or more GameObjects into a RenderTexture and then erase from it afterward.
|
|
We create and add a new RenderTexture to the Scene on line 27. We want to make sure it sits on top of the reveal image so it uses the same x and y values and an origin of 0.5, 0.5.
Then we draw the cover image into the RenderTexture on line 29. Lastly, we tint it red with the hexadecimal value 0xcc0000.
The last two parameters passed to rt.draw() on line 29 is an x and y offset. We can omit this if we change the cover image's origin from a default of 0.5, 0.5 to 0, 0 like this:
cover.setOrigin(0, 0)
// ...
rt.draw(cover)
Which approach you take doesn't matter. Just know that none of this is magic! 🦄 It's just math. 🤓
If you run this you should see a red-tinted Phaser logo.
Erasing with a Brush
Next, it is time to erase from the RenderTexture and reveal the non-tinted Phaser logo.
The interaction for erasing will be moving the mouse while holding down the left mouse button.
|
|
First, we add an isDown property on line 12 to track whether the mouse button is pressed. Then we set our RenderTexture to interactive on line 43 and register 3 events: POINTER_DOWN, POINTER_MOVE, and POINTER_UP
The handler functions for POINTER_DOWN and POINTER_MOVE start on lines 56 and 62. The logic for POINTER_UP was so simple that we used a lambda that simply sets isDown to false.
After that, we create a brush and save the RenderTexture for later use in handlePointerMove(pointer).
The revealing logic is on line 71 where we call this.renderTexture.erase() and pass in the brush and location.
And that is the complete code example! You should see something like this:
Next Steps
This object reveal method is simple and lightweight. It works well in cases where the cover image completely hides the reveal image.
For more complicated cases or effects, there is the alpha mask approach that we will demonstrate in the next article.
Let us know in the comments below if anything doesn’t work or is unclear. We’ll be happy to fix or clarify!
Be sure to sign up for our newsletter so you don't miss any future Phaser 3 game development tips and techniques!
Drop your email into the box below.
Don't miss any Phaser 3 game development content
Subscribers get exclusive tips & techniques not found on the blog!
Join our newsletter. It's free. We don't spam. Spamming is for jerks.