In 2D games, it is not uncommon to want animated backgrounds. Having static images in your levels doesn’t necessarily add to the game-play experience, so a little bit of motion can go a long way.
So how can you do this without having to manage these background images like you would a typical sprite?
Rather than worrying about creating, destroying, and managing sprites to represent components of your background, it might make sense to use a tile sprite, sometimes referred to as a tilemap. With a tile sprite you are grabbing tiles from an image and using them wherever you might need them. This approach is common for game backgrounds or levels that have a lot of asset repetition because it takes less resources and will leave you with a higher performance game.
In this tutorial, we’re going to see how to use a tile sprite in a Phaser 3.x game to add an infinite scrolling effect to the background in our game.
To get an idea of what we want to accomplish, take a look at the following animated image:
In the above Phaser 3.x game, there are two images, one with large clouds and one with small clouds. These images both have the same resolution as the game canvas. As these images scroll off the screen, they are added again to the other end to give us a continuous scrolling effect without having to manage each individual cloud.
Before we get into the core material of this particular tutorial, we need to set the foundation of our project, and by foundation I mean add a bunch of boilerplate Phaser 3.x code.
On your computer, create a new directory and within that directory create an index.html file. Within that index.html file, add the following markup:
<!DOCTYPE html>
<html>
<head>
<script src="//cdn.jsdelivr.net/npm/phaser@3.24.1/dist/phaser.min.js"></script>
</head>
<body>
<div id="game"></div>
<script>
const phaserConfig = {
type: Phaser.AUTO,
parent: "game",
width: 1280,
height: 720,
backgroundColor: "#5DACD8",
scene: {
init: initScene,
preload: preloadScene,
create: createScene,
update: updateScene
}
};
const game = new Phaser.Game(phaserConfig);
var cloudsWhite, cloudsWhiteSmall;
function initScene() { }
function preloadScene() {}
function createScene() {}
function updateScene() {}
</script>
</body>
</html>
Most of what we do for this tutorial will be done in the preloadScene
, createScene
, and updateScene
functions. Take note that we have a cloudsWhite
and cloudsWhiteSmall
variable which will represent each of our two images.
With the project containing our boilerplate code, we can proceed to working with our tile sprites.
Before we start looking at creating tile sprites, you should have already created images to be used in this example. To make life a little easier, you can use the images that I’m using.
The first image represents the larger of the clouds:
The second image represents the smaller of the clouds, which in our example, are scrolling at a slower speed to try to demonstrate depth in our background animations:
Take note of the width of both images and then take note of the width we defined when configuring Phaser. While the widths match in this example, they don’t need to. I made them match because it makes the images a little easier to scroll in my opinion.
Now that we have some images to work with, let’s update the preloadScene
function of our index.html file:
function preloadScene() {
this.load.image("clouds-white", "clouds-white.png");
this.load.image("clouds-white-small", "clouds-white-small.png");
}
Make sure to use the path to your images. In my example, the images are at the same path as my code.
With our images loaded, we can create tile sprites from them. Within the createScene
function of our index.html file, include the following code:
function createScene() {
cloudsWhite = this.add.tileSprite(640, 200, 1280, 400, "clouds-white");
cloudsWhiteSmall = this.add.tileSprite(640, 200, 1280, 400, "clouds-white-small");
}
Probably the most difficult part to grasp of the above lines is in regards to the position and size of our tile sprite. The images I’m using in this example have a resolution of 1280x400, hence the size used in the tile sprite. When positioning the images, note that you’re working with the center point of the images. If I wanted to give the illusion that these clouds are at the top of the game, we would need to use half of whatever the image dimensions are.
The sizing and positioning took me a while to grasp, but it wasn’t too bad.
With a properly defined tile sprite, now we can start moving them. In the updateScene
function, add the following code:
function updateScene() {
cloudsWhite.tilePositionX += 0.5;
cloudsWhiteSmall.tilePositionX += 0.25;
}
The above code will move our tiles at two different speeds. The tiles will scroll to the width of the game canvas and repeat.
You just saw how to scroll a background infinitely using tile sprites in a Phaser 3.x game. Not only are tile sprites great for performance reasons, but the simple act of animating your backgrounds can add a new level of depth to your already amazing game.
The way we scroll or animate tile sprites is different than we would be animating player or typical sprites. If you’re interested in creating a sprite animation based on frames, check out my previous tutorial on the subject titled, Animate a Compressed Sprite Atlas in a Phaser Game.