The quicksand effect is somewhat common in platformers but you probably haven't found too many tutorials for it. 🤔
Unlike something simpler such as water or lava, quicksand might take a few days to figure out and implement.
In this article, we'll show you how to create a basic quicksand effect for a Phaser 3 game using Arcade Physics!
We will assume that you are making a platformer with player logic already implemented and using tilemaps but not necessarily from Tiled.
Drop your email into the box below to get this free 60+ page book and join our newsletter.
Scene set up code has been omitted so that we can focus directly on creating a
Quicksand class that can be used in a Scene you already have.
Creating the Quicksand Class
Quicksand class will create an object that is placed over the tiles representing quicksand.
We don't have any animations in our tiles but they can be added separately from the quicksand logic.
This is what the quicksand effect will look like 👇
Let's start with a basic skeleton:
Notice that we are not extending from an existing Phaser class. Instead, we are just going to create the visual elements we need and keep a reference to them.
In the constructor, we create an invisible
Rectangle on line 17 with an origin set to the bottom left corner. This is for ease of positioning in this example. You may prefer to keep it t at
(0.5, 0.5) or
Then we inject Arcade Physics components into the
Rectangle on line 20. We'll add a collider with the player instance in the Game Scene later.
Creating the Quicksand Effect
With a physics-enabled
Rectangle, the player will be able to stand on it but not sink into it. The sinking effect will be created by adjusting the size of the
Rectangle collision box.
We'll start making the
Rectangle smaller as soon as the player collides with it. Then if the player jumps or is no longer touching the collision box, we will expand the size of the
Quicksand is also harder to move through so we will clamp how high the player can jump while in quicksand.
Let's start by adding a
handleCollidePlayer() method and a
touchingPlayer class property to store the player instance when it collides with the
Note that this quicksand example assumes only 1 player character. There will be more work involved to have it support multiple players and is outside the scope of this article.
handleCollidePlayer() method will be set as the callback when we create a collider in the Game Scene.
Next, let's create a
changeCollisionBoxBy(diff) method that will adjust the size of the
Rectangle collision box. We'll use it in the
update() method to make the collision box bigger or smaller depending on what the player is doing.
Notice that we don't do anything if the collision box is as big as the display's original height or if it is already zero or less. These two checks are on lines 7 and 12.
Then on line 18, we set the offset so that the collision box changes height while being anchored to the bottom. Without this offset, you'll see that the height shrinks and expands from the middle.
Now, we can implement the core quicksand logic in
First, we early exit and do nothing if
this.touchingPlayer is not set. This means that the player is not currently in a quicksand area.
Then we do some logic to determine if the player is touching the collision box or within the bounds of the quicksand display.
We do this because the player can be surrounded by quicksand while jumping. This would result in the player not colliding with the collision box but still being affected by quicksand.
The collision box will continue to shrink as long as the player is touching it unless a jump occurs. Then the collision box will expand instead. This will allow the player to eventually jump out of the quicksand even though jump height is reduced.
That jump height reduction happens on line 26.
Finally, the last check on line 32 will determine when the player has jumped out of the quicksand area and should no longer be affected. We remove the reference to the player and immediately set the collision box to full size.
If the player lands on the quicksand again then the sinking effect will start over from the beginning.
Using the Quicksand Class in a Scene
Quicksand class can be easily used by creating a new instance in the
create() method like this:
We are assuming that the player instance is stored in a
player variable. Your actual game code may be different.
Notice that we use the
handleCollidePlayer() method from the
Quicksand class as the collider callback. We also pass in the
quicksand reference as the
The position and size values that we are using to create a new
Quicksand instance are just for this example and your game code will probably be different.
If you are using an editor like Tiled then you will want to use objects on an Object Layer. That data can then be used to create a
Quicksand instance with the right position and size.
Lastly, we'll want to call the
update() method on the
quicksand instance in the Scene's
update() method. You may need to create a class property with the
quicksand reference to do this.
Be sure that the player's movement logic is run before the call to
update() on the
Quicksand instance. Otherwise, clamping the player's movement speed from the
Quicksand class won't work.
Quicksand object is a good example but not realistic for a game.
Odds are your level will have a few quicksand areas for the player to deal with.
Quicksand class we made easily supports multiple instances. All you need to do is to add a collider and call the
update() method for each created
It'll look something like this:
Then in the Scene's
The main difference to note is that we created an
Array class property called
quicksands to store each created
The end result should look something like this 👇
Quicksand is definitely more complicated than just adjusting physics for water or taking damage from landing in lava but not impossible!
We didn't go over how to determine when the player is so deep that they suffocate and we'll leave that to you.
Other physics values can be adjusted or clamped when the player is inside of quicksand as well. It may be similar to how we clamp the player's jump height.
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.