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.
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.
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.
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:
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
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 👇
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
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!
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.