Buttons are commonly used in game menus and UI but they are not built into Phaser 3.
GameObject in Phaser can be made interactive and respond to events like up, out, and over.
This means we can make a button pretty easily!
In this article, we will look at creating a basic button in Phaser that uses RxJS to dispatch click events.
Reactive programming provides a clear, concise, and clean way to deal with real-time events like UI interactions, API responses, and more.
It makes implementing a feature like double click clear and trivial compared to doing it the traditional way.
This code is taking a stream of
click events that get buffered for 300 milliseconds, then filtered for groups with only 2 events, and then returns the last event to subscribers. Tada! Double click detected.
We won't go into the specifics of RxJS in this article but let us know in the comments below if you'd like to learn more about how you can use it in your games.
Creating a Button
A button is just an object that responds to
GameObject in Phaser can listen for those events and respond accordingly.
For example, a button can change color or texture for each of those events.
Because a button is visual, we are going to subclass
Phaser.GameObjects.Image and then add some button specific logic.
The code is in TypeScript and quite long but it is all very simple. 👌
Starting at the top of the class we have a
texture property for each state the button can be in:
The starting values given to the
constructor will be the values for the
tint values can then be changed by their respective set methods like
setOverTexture(texture: string) and
We set the button to interactive on line 31 and then register listeners for each event.
And that's the core logic for display and interaction. Simple!
Handling Click Events
Button class we just made can be displayed in a
Scene and respond to events but there's no designated
We can use
.on(Phaser.Input.Events.GAMEOBJECT_POINTER_UP, handler) but we will leverage the power of RxJS instead. 💪
You'll need to run
npm install rxjs to import
Subject like we are doing on line 3. We are also using the phaser3-parcel-template to bootstrap this example project.
Subject is created on line 9 that will handle dispatching events.
There will often only be a single observer listening to a
click event but there is no reason why two or more can't be listening as well. A
Subject is a special
Observable that allows broadcasting to multiple observers so it is well suited for this job.
Line 15 is just some cleanup where we set the
Subject to complete.
Then on line 20 is the
onClick() method that returns an
Observable from the
clickSubject. This is how external code using the
Button class will listen for
And finally, on line 31 we dispatch a
click event by calling
this.clickSubject.next() and passing in the
pointer instance. Any code listening for
click events from this button will be notified immediately. 🎉
Putting it in a Scene
Let's see our
Button class in action by putting it in a Scene.
We will be using image assets from Kenney's platformer pack.
The key lines are 32 where we create the button and then line 36 where we add it to the Scene.
Then on line 38, we use the
onClick() method to get an
Observable and subscribe to it.
Each time a
click event happens we spawn a gem that will bounce around the screen randomly.
It should look something like this:
Buttons often have text. Something like “Play” or “Settings”.
You can add text using
this.add.text() and placing it at the same location as the
Text we added on line 14 is a completely separate
GameObject so you will have to update its position whenever you move the
Phaser was designed to have a flat hierarchy. This may seem odd if you've used Flash, cocos2d, or other popular game frameworks.
Instead of allowing every
GameObject to have children, Phaser has a special
GameObject called a
Container that can be used to group objects together.
You can now make a simple button that can change textures or colors on different states and respond to
In the next article, we will look at using a
Container to group a
Text instance together so that they can be moved, scaled, rotated, and manipulated as one object.
Let us know in the comments below if anything doesn’t work or is unclear. We’ll be happy to fix or clarify!
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.