Are you are making a roguelike or dungeon crawler?
Do you want the player to only see what is visible based on where they are standing?
Where enemies or items behind a wall, in the next room, or around the corner should be hidden until the player has line of sight?
Then what you need is a proper field of view algorithm.
In this article, we will go over using the MRPAS algorithm to implement a field of view effect in Phaser 3 with tilemaps.
MRPAS is a restrictive field of view algorithm that stands for Mingo's Restrictive Precise Angle Shadowcasting.
This algorithm generally produces a visually appealing and more natural-looking field of view than other algorithms and is popular amongst roguelikes.
It is probably used in a roguelike you recently played!
In this example, we will be using the mrpas NPM package.
You can install it in your project using this command:
npm install mrpas
Setting Up Mrpas in a Scene
Drop your email into the box below to get this free 60+ page book and join our newsletter.
Note that we are going to skip over the tilemap set up code and focus on using the
Here's what the Scene looks like:
We are importing the
mrpas library on line 3.
Then on lines 23 - 26 we create an
Mrpas instance and store it in the
fov class property.
Mrpas constructor takes width, height, and a function used to determine if a tile can be seen through. The opposite of things like a wall or door–unless you are Superman.
We set it to the inverse of
tile.collides which means anything that cannot collide with the player can be seen through.
For example, a floor tile will not block vision. A wall tile will block vision.
Using the Field of View
Getting the field of view effect to work takes just 3 steps:
1. Hide all the tiles. 2. Use MRPAS to calculate the tiles within the field of view. 3. Only make those tiles visible.
To start, add this method to your Scene:
Notice that we are only turning off tiles that the camera can see. Anything outside of the current camera view is ignored.
To hide the tile we simply set
0 on line 33.
Add a call to
this.computePOV() in the Scene's
update() method and your tiles should no longer be visible.
Next, let's calculate FOV and turn on the visible tiles.
We get the current position of the player and then use it as the origin in our call to
this.fov.compute() on line 10.
7 on line 13 is the radius. Make this bigger or smaller to adjust the field of view size. You can also use
The next two arguments are where the magic happens.
First, is a function that should return whether a tile is currently visible or not. That is determined by
alpha greater than
Next, is a function that sets a tile to be visible. We do that by setting the
Try this out and tiles within the field of view will appear while others will disappear.
We can make this effect a little nicer by tinting invisible tiles a dark color and fading out tiles furthest from the player.
Only 3 changes are needed:
First, instead of setting
alpha = 0 when we loop through the visible tiles, we set
alpha = 1 and add a
0x404040 on lines 12 and 13.
Then we change our check for whether a tile is visible or not from
tile.alpha > 0 to
tile.tint === 0xffffff. This means a tile with no tint or a white tint is assumed to be visible.
Lastly, we adjust
alpha based on the distance from the player for tiles that are in the field of view on lines 38 - 42.
You should get something that looks like this:
We used a single tile layer to keep the example code simple. You will have to handle any other layers that you might have.
There are more things you can add like fading the tiles as they go in and out of visibility.
An alternative to tinting tiles is to add another layer with only black tiles that you fade in and out. This can also be used to keep unexplored sections hidden.
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.