Navigation

All about the 3.16.2 Release and a guide on the new Key events.

Published on 11th February 2019

Welcome to another new Dev Log. It's been nearly a week since the release of Phaser 3.16 and, for the most part, things seem to have gone ok. Given the volume of changes, there were bound to be some errors in the release, yet most of them don't appear to have been as dramatic as they could have been. Which is always a good thing.

I tend to feel anxious pushing out any release, never mind one as large as 3.16 was. When thousands of people rely on what you're building it just increases the general sense of panic that perhaps you left something broken in there without realizing it. All I can do is jump on the issues as quickly as possible and prepare for a new release. Which is what I spent last week doing and it results in ...

image

3.16.2 Release

The plan was to release 3.17 next, which was going to be a maintenance release, focusing on issues that 3.16 introduced and some older ones too. However, as it turns out, there were some bugs in 3.16 that need addressing sooner rather than later, so I've just released 3.16.2 today. This version fixes the following:

1) Mesh and Quad throw errors when added to Containers. I removed some redundant methods from Mesh in 3.16, such as setAlpha, as they didn't do anything so I felt they were misleading being there. However, when you put a Mesh into a Container it needs them. So, I've introduced the missing methods back and we're all good again.

2) The Keyboard method checkDown would never return the correct result because of the change to the event system. It would check a time value against the key that wasn't being set any longer, causing this method to fail. I've modified the way the input systems get the current time, so this method (and possibly others) work again properly.

3) Entering Fullscreen mode in the Scale Manager and then pressing the ESC key to exit would leave the injected fullsceen div in the DOM, causing it to throw a node insertion failure the second time you wanted to enter fullscreen mode.

4) Due to the changes in the Input event system, the GAME_OUT event would never fire unless the input system was in legacy mode. The OUT and OVER handlers have been refactored and will now fire as soon as the DOM event happens. As a result the InputManager.\_emitIsOverEvent property has been removed, as the native event is sent directly to the handler and doesn't need storing locally any more.

5) Added Zone.setBlendMode method as a NOOP function, fixing a bug where if you added a Zone to a Container when running under Canvas it would fail.

6) Fixed an error in the TypeScript defs that caused them to conflict if you were also using defs from Angular or Node.js.

As well as this, I also updated a few other methods, including Matter.World.remove, so that it now uses the internal Composite.remove methd instead, making it far more flexible than before without losing any features or changing the method signature.

Thanks to a PR from @rgk Touch inputs will now emit POINTER OUT events if they leave the game (i.e. are released). Previously, you'd only get a POINTER UP event, but now you get both, just like on desktop.

Matter Pointer Constraint Changes

The following changes all effect the Matter JS Pointer Constraint class:

▪ Pointer handling has been changed to make more sense. In the previous version, pressing down and then moving the Pointer over a body would start it being dragged, even if the pointer was pressed down well outside of the body bounds. Now, a body can only be dragged by actually pressing down on it, or any of its parts, which is more in-line with how input events should work.
▪ Previously, releasing ANY pointer would stop an object being dragged, even if it wasn't the one actually dragging a body, as in a multi-touch game. Bodies are now bound to the pointer which started their drag and only the release of that pointer will stop them.
▪ There is a new Matter Physics Event DRAG\_START which is emitted by a Pointer Constraint when it starts dragging a body. Listen for this event from the Matter World instance.
▪ There is a new Matter Physics Event DRAG which is emitted by a Pointer Constraint as it drags a body. Listen for this event from the Matter World instance.
▪ There is a new Matter Physics Event DRAG\_END which is emitted by a Pointer Constraint when it stops dragging a body. Listen for this event from the Matter World instance.
▪ The camera property can no longer be set in the config object. Instead it is set every time the Pointer is pressed down on a Body, this resolves issues where you have a multi-camera Scene and want to drag a body in the non-main camera.
body is a new property that holds a reference to the Body being dragged, if any.
part is a new property that holds a reference to the Body part that was clicked on which started the drag.
▪ The internal getBodyPart method has been renamed to hitTestBody to more accurately reflect what it does.
▪ The class no longer listens for the pointer up event, instead of tracks the active pointer and waits for that to be released. This has reduced the complexity and size of the update method considerably.
stopDrag is a new method that allows you to manually stop an object being dragged, even if the pointer isn't released.
▪ This class now has 100% JSDocs.
▪ Pointer handling has been changed to make more sense. In the previous version, pressing down and then moving the Pointer over a body would start it being dragged, even if the pointer was pressed down well outside of the body bounds. Now, a body can only be dragged by actually pressing down on it, or any of its parts, which is more in-line with how input events should work. ▪ Previously, releasing ANY pointer would stop an object being dragged, even if it wasn't the one actually dragging a body, as in a multi-touch game. Bodies are now bound to the pointer which started their drag and only the release of that pointer will stop them. ▪ There is a new Matter Physics Event DRAG\_START which is emitted by a Pointer Constraint when it starts dragging a body. Listen for this event from the Matter World instance. ▪ There is a new Matter Physics Event DRAG which is emitted by a Pointer Constraint as it drags a body. Listen for this event from the Matter World instance. ▪ There is a new Matter Physics Event DRAG\_END which is emitted by a Pointer Constraint when it stops dragging a body. Listen for this event from the Matter World instance. ▪ The camera property can no longer be set in the config object. Instead it is set every time the Pointer is pressed down on a Body, this resolves issues where you have a multi-camera Scene and want to drag a body in the non-main camera. ▪ body is a new property that holds a reference to the Body being dragged, if any. ▪ part is a new property that holds a reference to the Body part that was clicked on which started the drag. ▪ The internal getBodyPart method has been renamed to hitTestBody to more accurately reflect what it does. ▪ The class no longer listens for the pointer up event, instead of tracks the active pointer and waits for that to be released. This has reduced the complexity and size of the update method considerably. ▪ stopDrag is a new method that allows you to manually stop an object being dragged, even if the pointer isn't released. ▪ This class now has 100% JSDocs.You can download Phaser 3.16.2 from the GitHub releases page, or pull it in via the npm package. There are also the pre-built files available on the jsDeliver CDN. The docs and TypeScript defs are all updated, too.

If any more issues surface that I consider important like these, then I'll build a 3.16.3 release. However, if not, then 3.17 will be the next version. I still fully intend for 3.17 to be focused on fixes rather than features, but I'm happy to spend a few weeks working on it, rather than rushing it out.

February Backers Examples

I'm pleased to say that the February Phaser Code Examples bundle has now been delivered to all backers on Patreon and PayPal. Sorry for the short delay as 3.16 got in the way. I had some real fun putting together this set of 10 fresh examples, which includes the following:

image

Mobile Buttons

This example was created specifically for one of the Phaser patrons but was useful enough to share with everyone. The original reason for creating it was to show how to make player controls for mobile devices that continue to fire even when held down. In the screen shot above you can see two buttons for left and right. Holding down on either of them makes the car move in that direction.

Initially, this seems really trivial, right? Yet to get it feeling really nice on an actual touch device it took a bit more planning and conditions than you may think. For example, if you hold down the left button then the car moves left as expected. If you then press the right button, while still holding left down, the car moves to the right (as it was the most recently active button pressed). If you then release the right button, but still have the left one held down, the car starts moving left again. In practise it feels much nicer to use than just having each button be an on/off toggle.

image

Ball Chain

If you use a version of Phaser with Matter.js built in, then you can create Distance Constraints between bodies. But what if you want to do this without adding the whole of Matter to your bundle, or having a physics simulation running? Thankfully, a basic verlet distance constraint is pretty straight-forward to create on its own, and this example shows how and includes a re-usable class.

image

A static screen shot doesn't really do this example justice. It shows what can be achieved using the Distance Constraint created for the Ball Chain and a little creative thinking. In the example, each petal is its own Sprite and there are constraints between them and the center of the flower, as well as between each other. By varying the stiffness and resting length we can create a lovely effect that simulates the flowing being blown in the wind.

These are just three of the 10 examples in this months collection.

If you back Phaser on Patreon then check your email for details on how to download this bundle. If you'd like to back Phaser, that's great! and you'll get instant access to this bundle and the previous ones as well.

image

Phaser CE 2.12.0

A new version of Phaser CE is now available. You can download it from GitHub and npm. There are a number of new features and updates, especially if you're using Phaser with the Creature animation package.

It includes a new Creature runtime, which has bought with it a few breaking changes from the old runtimes but also powerful new features like enabling skin and item swapping. Also in this release is the ability to set letter spacing between Bitmap Text characters, which works in addition to kerning values.

There are also bug fixes. In fact, one of them, to do with the volume and mute state of HTML5 audio, I actually fixed myself! It's the first time I'd been back into the Phaser CE code in months. To be honest, it felt like putting a pair of comfy slippers back on :) and it was nice to contribute a fix to the community edition of Phaser.

image

Phaser 3.16 Tutorial: Input Keys

This is a continuation from last week where I'm going to discuss the new features in 3.16 in more detail. Last week I talked about External Scene Files. This week let's cover the changes to the Key objects and how you can now use them.

One of the most important changes in 3.16 was to do with the events being used through-out the API. Events are now properly namespaced, which means you don't have to rely on remembering the string-based keys any more. For example, you can now do this:

image

Which looks quite verbose in that form. But, if you are using a bundler, you can import the Keyboard Events directly, which makes it a lot more concise:

image

Of course, you can still use the string form of the event name, too. But the constants are really a lot safer. They protect you from typos and from the API potentially changing the name of an event, which is another thing that happened in 3.16 that you should absolutely be aware of:

keydown_A to keyboard-A

With all the work I did on events in 3.16 I consolidated the way that they were all named. This meant that, in cases where the API has dynamic events based on the key of something, the delimeter is now consistently a hyphen for every event. This makes more sense with an example. Looking at the following two lines of code and spot the subtle difference between them:

image

Here all we're doing is listening for the A key to be pressed down. Yet there is an important difference. It's a tiny change on the surface, the underscore splitting-up the event name with the dynamic string, in the old 3.15 format, to a hyphen in 3.16, but it's a really vital one to be aware of.

All dynamically named events now use the hyphen format. You'll also see them in the Loader, Animation system and elsewhere. So, if you are using 'keydown' in your game code anywhere, change it right now_. Either swap the underscores for a hyphen, or use the new constant event names instead to build your listener handle. In 3.16 both the underscore and hyphen work for keyboard events, but in 3.17 the underscore will be dropped entirely as it's now deprecated.

Key Events

New in 3.16 is the fact that Key objects are now event emitters themselves.

What's the difference between a Key object and a keyboard event? The difference is that keyboard events are 'single fire' actions. When you press a key down, you get a keydown event. If you release it, you get a keyup event. However, all that time inbetween is important too. If you're making an action game and you need to poll the state of a key in realtime, i.e. to move a player left or right, then you can create a Key object and poll its 'isDown' property in your update loops, then act accordingly. Where-as a keydown event is more for things that you need as a toggle, i.e. pressing M to mute the sound.

I felt it was a bit of a pain to need both all the time, though. After all, the Key objects were internally just responding to the keyboard events anyway, so to keep things clean I allowed a Key instance to emit 'down' and 'up' events as well. Take a look at the following code:

image

Here you can see that I've created a new Key object that monitors the space bar, but I can also now listen to the 'down' event from it, too. This wasn't possible before 3.16, previously you would have had to needed both the Key object and a keydown listener as well.

I also implemented a more rigid event flow in 3.16 with the ability to stop the propagation of the event. In 3.16 a keyboard down event now flows as follows, from top the bottom (in this example for the space bar):

Phase 1: Key.on('down') event
Emits only when the SPACE BAR is pressed down, and dispatches from the local Key object.

Phase 2: Global keydown + keycode handler: 'keydown-SPACE'
Emits only on the SPACE BAR keycode event, but dispatches globally.

Phase 3: Global keydown handler: 'keydown'
Fires on ANY key press, so we need to check the keyCode internally to see if it's the space key.

You can also now call event.stopPropagation at either the phase 1 or 2 levels, which will stop the event from reaching any listeners defined at a phase below.

Have a look at the following example to get an idea. Click the Edit button below the demo to view the source for it to make sense, and try un-commenting some of the stopProagation calls too, to see how it blocks what happens.

image

Keys emitting their own events, the flow process and the ability to half the events are all small changes, yet when packed together they provide a lot more control than previously. So please, go forth and create Keys and poll them and update them as you need :)

That's all for this Dev Log. Work this week will continue on 3.17, as well as some other non-coding, Phaser-related tasks. More on that next issue.