How to Create a Fast Loading Animation in Phaser 3

Couple loading animations with async operations for a better user experience

by on 6 minute read


If you are making asynchronous requests that can take several seconds to resolve then you'll want to have a loading animation.

Many players have short attention spans and little patience these days. If a game looks frozen, stalled, or appears to be broken then they'll move on to the next game.

The fierce level of competition has driven up the expected level of polish for UX or user experience. As a developer, this can feel like additional work that doesn't differentiate your game.

That's why we've created 30 that you can just drop into your Phaser 3 game here.

In this article, we'll show you how to create a simple loading animation using native Phaser 3 GameObjects and Tweens without having to download any extra art assets. It'll be fast and light plus allow you to layer it between Sprites, unlike CSS animations.

Activity Indicator

Apple's activity indicator has probably become one of the most iconic loading animations. It is a ring of bars that animate in a staggered spin order.

It looks like this 👇

Anyone who sees this animation will understand that an app or game is doing something and we should wait.

Given that October 5th marks the day that Apple's iconic co-founder, Steve Jobs, passed away we thought it would be fitting to show you how to create this iconic loading animation today.

Check out Phaser Loading for a pre-made and customizable version of this animation.

Creating the Rectangles

We can breakdown this animation and see that there are 12 rectangles around the perimeter of the circle that is rotated to point out from the center.

The example here will keep all the code in a single createLoadingAnimation() method that is part of a Scene for simplicity.

Let's start by laying out the rectangles around the circle:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
createLoadingAnimation()
{
	// store the bars in a list for later
	const bars = []

	const radius = 64
	const height = radius * 0.5
	const width = 10

	// the center of the loading animation
	const cx = 400
	const cy = 300

	// start at top
	let angle = -90

	// create 12 bars each rotated and offset from the center
	for (let i = 0; i < 12; ++i)
	{
		const { x, y } = Phaser.Math.RotateAround({ x: cx, y: cy - (radius - (height * 0.5)) }, cx, cy, Phaser.Math.DEG_TO_RAD * angle)

		// create each bar with position, rotation, and alpha
		const bar = this.add.rectangle(x, y, width, height, 0xffffff, 1)
			.setAngle(angle)
			.setAlpha(0.2)

		bars.push(bar)

		// increment by 30 degrees for next bar
		angle += 30
	}
}

This code can be a bit confusing as you have to visualize where each bar is and how they are rotated and then convert that to math.

We have the cx and cy variables that designate the center of the loading animation. From there, we create rectangular bars starting from the top (or the 12 o'clock position) and place them at the perimeter of the circle as calculated on line 20.

Each bar is also rotated to the current angle value so that they are pointing out from the center.

All bars are added to an array so that we can perform a tween to fade them in a staggered manner later.

Staggered Fade Animations

The first thought for creating this animation might be to use a Timeline but that won't quite work because the animation needs to be continuous.

A Timeline will play all the tweens and then restart but that will result in the fade animation of the first bar restarting only after the last bar has finished fading out. If you look at Apple's animation carefully, you'll see that the first animation starts before the last animation is finished as it loops back around.

So instead of a Timeline, we'll use a TimerEvent that fires every 70 milliseconds and loops forever. We'll keep track of which bar was last animated and then each time the TimerEvent fires, we'll animate the next bar.

Add this after the previous code 👇

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
createLoadingAnimation()
{
	// previous code...

	let index = 0

	// save created tweens for reuse
	const tweens = []

	// create a looping TimerEvent
	this.time.addEvent({
		delay: 70,
		loop: true,
		callback: () => {
			// if we already have a tween then reuse it
			if (index < tweens.length)
			{
				const tween = tweens[index]
				tween.restart()
			}
			else
			{
				// make a new tween for the current bar
				const bar = bars[index]
				const tween = this.tweens.add({
					targets: bar,
					alpha: 0.2,
					duration: 400,
					onStart: () => {
						bar.alpha = 1
					}
				})

				tweens.push(tween)
			}

			// increment and wrap around
			++index

			if (index >= bars.length)
			{
				index = 0
			}
		}
	})
}

The key thing to note about this code is that we are reusing tweens by saving them to an array. We create a tween for each bar once and then just restart it the next time.

You can play around with the delay, duration, and alpha values to change how the animation feels.

Give this a try and you should see the classic Apple activity indicator animation created with native Phaser 3 GameObjects. 🎉

The benefit of having created this natively in Phaser 3 is that you can layer it between UI elements or even in-game items like doors that need to load assets before opening and the player will still render in-front as expected!

Next Steps

Another way to use this animation is to add it to a Container so that you can move all the bars together.

It also works great as a way to provide feedback to the player when you are lazy loading images like we talked about here.

If you would like to save time and get access to a growing selection of fast and efficient loading animations like the one we created here then check out Phaser Loading. We created each animation as a standalone class so that you can just drop it into your game with minimal dependencies. 😎

Plus each animation is just $1.50 and you can use it in all your games and projects. Forever.

Go visit Phaser Loading for this great deal on playful loading animations!

Phaser 3 loading animations spinners indicators

Want tips and techniques more suited for you?


You may also like...


Video Guides


Beginner Guides


Articles Recommended For You

Fix Stretched Image Distortions in Phaser 3 with 9-Slice Scaling

by on

Are you having image distortion problems when scaling to make a button or panel graphic bigger? Multiple versions of the …

5 minute read

Command Pattern to Undo Player Actions

by on

Are you looking for a clean and reusable way to implement undo for player actions? Perhaps you are making a turn-based …

15 minute read

Advanced Logging with the Strategy Pattern

by on

Have you ever tried debugging a problem with your game that only seems to happen in production? The Developer Tools …

7 minute read

State Pattern for Character Movement in Phaser 3

by on

Writing clean and well-organized code is something all game developers aspire to. We want code to be reusable and easy …

7 minute read

Didn't find what you were looking for?


comments powered by Disqus