Buttons are commonly used in game menus and UI but they are not built into Phaser 3.
However, every 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.
Why RxJS?
RxJS is a reactive programming library for JavaScript that combines the Observer pattern, Iterator pattern, and functional programming.
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 mouse_up, mouse_down, mouse_over, and mouse_out events.
Any 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 tint and texture property for each state the button can be in: up, down, over, or disabled.
The starting values given to the constructor will be the values for the up state. texture and tint values can then be changed by their respective set methods like setOverTexture(texture: string) and setOverTint(tint: number).
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
The Button class we just made can be displayed in a Scene and respond to events but there's no designated click event.
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.
A 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 click events.
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:
Adding Text
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 Button.
|
|
The Text we added on line 14 is a completely separate GameObject so you will have to update its position whenever you move the button.
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.
Next Steps
You can now make a simple button that can change textures or colors on different states and respond to click events.
In the next article, we will look at using a Container to group a Button and 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.