Create an Animated Health Bar in Phaser 3

Add polish to your game with animated health bars constructed from image segments

by on 6 minute read


Using simple numbers to show health is great for prototypes. It is quick to create when you are testing gameplay.

You'll want more polished elements as you advance to the next stages of development.

That's where health bars come in. They are the next level of polish above just numbers. An animated health bar is another level above that.

In this article, we will look at creating an animated health bar that is made up of 3 image segments for your Phaser 3 game.

Project Set Up

We'll be using the UI Pack: Space Expansion assets by Kenney.

The horizontal bar assets are composed of 3 parts: left end, middle, and right end.

There's also a set of shadow assets that will be used to show the full size of the bar as it drains or fills.

The example code assumes a project using the phaser3-parcel-template that places static assets in a public folder.

This information should help you adapt the examples to your game.

The project template and examples in this article use modern JavaScript. If you are not familiar with that then we have a free book to help you out!

Learn to make an Infinite Jumper in Phaser 3 with modern JavaScript!

Drop your email into the box below to get this free 60+ page book and join our newsletter.

Learn more about the book here.

Load Bar Assets

We are using the green bar segments as well as the corresponding shadow segments.

The shadow segments will be placed under the green bar so that we can visually tell 50% from 100%.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
preload()
{
	this.load.image('left-cap', 'assets/barHorizontal_green_left.png')
	this.load.image('middle', 'assets/barHorizontal_green_mid.png')
	this.load.image('right-cap', 'assets/barHorizontal_green_right.png')

	this.load.image('left-cap-shadow', 'assets/barHorizontal_shadow_left.png')
	this.load.image('middle-shadow', 'assets/barHorizontal_shadow_mid.png')
	this.load.image('right-cap-shadow', 'assets/barHorizontal_shadow_right.png')
}

We key the individual segments based on their position: left, middle, or right. Then the corresponding shadow segments have a -shadow suffix.

Create Shadow Bar

The shadow bar will be created first so that it will be rendered behind the health bar.

We will also need to specify a width size that represents the bar at 100% filled. It will be set as a class property in init().

1
2
3
4
init()
{
	this.fullWidth = 300
}

You are free to use any number you want. We are using 300 in this example.

Now, let's create the shadow bar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
create()
{
	const y = 24
	const x = 10

	// background shadow
	const leftShadowCap = this.add.image(x, y, 'left-cap-shadow')
		.setOrigin(0, 0.5)

	const middleShaddowCap = this.add.image(leftShadowCap.x + leftShadowCap.width, y, 'middle-shadow')
		.setOrigin(0, 0.5)
	middleShaddowCap.displayWidth = this.fullWidth

	this.add.image(middleShaddowCap.x + middleShaddowCap.displayWidth, y, 'right-cap-shadow')
		.setOrigin(0, 0.5)
}

Notice that we set the origin to (0, 0.5) for all the segments. This makes it easier to calculate where each segment should go relative to each other.

The origin we've selected is the middle left of the segment. This lets us use the x position and width of one segment as the position of the next segment.

The middle segment needs to sit next to the left segment and the right segment needs to sit next to the middle segment.

Because the middle segment will be variable width depending on the health value, we are using displayWidth on line 14 when specifying where the right segment should be placed.

The starting width of the middle segment is set on line 12 to be this.fullWidth.

Create Health Bar

The health bar is almost identical to the shadow bar that we just created.

The key difference is that we want the segments to be stored as class properties. This will allow us to animate it later.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
create()
{
	// previous shadow bar code...

	// health bar
	this.leftCap = this.add.image(x, y, 'left-cap')
		.setOrigin(0, 0.5)

	this.middle = this.add.image(this.leftCap.x + this.leftCap.width, y, 'middle')
		.setOrigin(0, 0.5)

	this.rightCap = this.add.image(this.middle.x + this.middle.displayWidth, y, 'right-cap')
		.setOrigin(0, 0.5)

	this.setMeterPercentage(1)
}

setMeterPercentage(percent = 1)
{
	const width = this.fullWidth * percent

	this.middle.displayWidth = width
	this.rightCap.x = this.middle.x + this.middle.displayWidth
}

Creating the actual health bar should be familiar. It uses the same origin and calculations as the shadow bar above.

Notice the setMeterPercentage(percent = 1) method that calculates the expected width of the meter based on the percent value.

We get the resulting width on line 20 by multiplying this.fullWidth with the given percent.

Then we set that value to this.middle.displayWidth and move the right segment based on this new width.

Try it out and you should see the bar change size depending on the value given as percent. If your character health is using values from 0 to 100 then you'll need to divide by 100 to provide a proper percentage.

Animating the Health Bar

Now that the basics are done, we can get to the sexy stuff!

We'll use a tween to animate the health bar from its current value to the desired new value.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
setMeterPercentageAnimated(percent = 1, duration = 1000)
{
	const width = this.fullWidth * percent

	this.tweens.add({
		targets: this.middle,
		displayWidth: width,
		duration,
		ease: Phaser.Math.Easing.Sine.Out,
		onUpdate: () => {
			this.rightCap.x = this.middle.x + this.middle.displayWidth

			this.leftCap.visible = this.middle.displayWidth > 0
			this.middle.visible = this.middle.displayWidth > 0
			this.rightCap.visible = this.middle.displayWidth > 0
		}
	})

This can seem like a lot if you are not familiar with tweens.

First, we created a new method with a similar signature to setMeterPercentage(percent = 1) from earlier. You can have both for simplicity or try to merge them into a single method.

We added an extra duration parameter to define how long it should take the bar to animate.

The desired width is calculated in the same way we've done before on line 3.

Then we create a tween with this.add.tween() and pass in a configuration.

The targets property is set to this.middle because that is the image we want to make bigger or smaller.

The displayWidth property is what we want to change on this.middle so we set it to the desired width. Then we give the duration and an ease value.

The onUpdate callback is used to move the right segment as the middle segment changes in size. Notice that we also adjust the visibility of the segments on lines 13 - 15 to ensure nothing is shown if the displayWidth is 0.

Give it a test by calling this.setMeterPercentageAnimated(0) after this.setMeterPercentage(1) in create().

You should get something that looks like this:

Next Steps

You can play around with different easing options to get a different feel.

If you need to move the health bar with a character or enemy then consider creating it in a Container.

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.

Phaser 3 health meter health bar meter

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