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.