Navigation

Phaser 3.3 News and Part 1 of a huge guide to Phaser Scenes.

Published on 31st March 2018

It's been a couple of weeks since the last Dev Log and the reason for this is that so much has been happening that I really struggled to find the time to write. It takes a lot of effort, many hours of work, to create the newsletter each week. I personally write all the articles on the site. I grab the screenshots, play the games, source the links and put it all together. Then I write the Dev Logs as well. In a typical week, it takes around 1.5 days to do all of these tasks, which is time I've been spending working on Phaser instead. I've tried getting people to help in the past, but even when offering to pay them they rarely last more than a few weeks and then I'm back to doing it on my own.

However, I know it's the main way in which you all read about what is happening, so I'll try to make sure we get back to being weekly again soon. I guess a little news often, is better than large dumps of news more sporadically.

And a heck of a lot has been happening. Massive amounts of work on the API Docs, TypeScript defs, the 3.3 release and all the work put into the 3.4 release being worked on at the moment. Plus we've Containers up and running too. So it's safe to say that if we skip a week for the newsletter it's literally only because Phaser itself is being advanced at such a rate.

Thank you to everyone who supports Phaser. We're nearly at the end of the funding received from Mozilla, so every little bit we get from Patreon and donations helps right now. If you can't contribute financially then please perhaps help with finding bugs, helping with the docs or just spreading the word about Phaser to your peers. It all helps :)

API Docs and TypeScript Defs

I've spent many days over the past couple of weeks working on the v3 documentation. This has entailed fixing no less than 1034 data-types, creating typedefs, refactoring the way certain classes export and endlessly testing, and re-testing the jsdoc export. It's a truly tireless task.

Progress has been great though and a couple of really good things have come out of this effort. First, I published the Phaser 3.3 API docs and they're now hosted on GitHub Pages, so you can browse them online:

Phaser 3 API Documentation

This is using the foodoc template, which isn't perfect but is much better than the alternatives. The downside is it takes just over 1 hour to generate the html, which is highly frustrating. I'm working hard on our own SQL based template, so you can do proper searches and cross-indexes and that will be presented on our web site. For now, though, the GitHub version is better than nothing. And at least all of the returns and data-types are accurate.

My thanks to community member orblazer for helping with so much of this work. As a result of our combined effort, Peter was finally able to complete his TypeScript Definitions generator. It took a lot of trial and error but we're now generating fully-compiling TypeScript defs direct from the Phaser source code.

You can download the TypeScript Definitions here.

This is our first pass at the defs. There are improvements to be had, but at least you can download them and use them in your projects. We will not be adding them in to our @typings package until they are more robust.

We have also published the source code to our TS Defs Generator (which itself is written in TypeScript) and you can find it, along with tests in the Phaser 3 Docs repo. See the README for more details.

If you would like to help refine the TS defs, or docs, then please do. I often get asked by people "when will the docs be ready?" but the truth of the matter is that, as of today, there are still over 7000 items in the API that need documenting. If you search the v3 source for the string '[description]', that is the tag we use to indicate that docs need to be written for that item. It may be a property, or a method, or a return statement or a function, but if it has that tag it means we've completed the data-type for it, but not the explanation as to what it is or does. Some are more obvious than others - if you come across one that you feel you could accurately describe then we would love a pull request from you to add it.

So, when will the docs be 100% complete? I don't really know. If we work together then perhaps quite soon. If I have to do them all on my own, then it's going to take several months at least. In the meantime, please stop asking, I'm afraid there is no magical docs fairy to write them for us, it's going to take hard work and nothing less.

image

Phaser 3.3 Release

Phaser 3.3.0 was released on March 20th and represented 10 days worth of development since the previous version. I'm sure you'll agree the Change Log is pretty epic given the quite short amount of time.

There are 32 new features in 3.3.0 and here are some of the highlights:

▪ Lots of new Game Configuration properties which are passed to the renderer, including power preferences, anti-aliasing, drawing buffer preservation and more.
▪ Arcade Physics can now wrap physics bodies around the world.
▪ Camera shake, fade and flash all now have optional callbacks that can be invoked when the effect completes.
▪ Camera fadeIn and Camera fadeOut are two new methods to help with scene transitions (also with callbacks)
▪ Groups now listen for the destroy event coming from children and automatically purge them from the Group if received.
▪ There is a new MatterGameObject which allows you to bind a Matter Physics body with any renderable Game Object, such as Text, Bitmap Text or TileSprite (see the labs for examples)
▪ The Sound Manager has new chainable setRate and setDetune methods.
▪ Lots of new Game Configuration properties which are passed to the renderer, including power preferences, anti-aliasing, drawing buffer preservation and more. ▪ Arcade Physics can now wrap physics bodies around the world. ▪ Camera shake, fade and flash all now have optional callbacks that can be invoked when the effect completes. ▪ Camera fadeIn and Camera fadeOut are two new methods to help with scene transitions (also with callbacks) ▪ Groups now listen for the destroy event coming from children and automatically purge them from the Group if received. ▪ There is a new MatterGameObject which allows you to bind a Matter Physics body with any renderable Game Object, such as Text, Bitmap Text or TileSprite (see the labs for examples) ▪ The Sound Manager has new chainable setRate and setDetune methods.Remember, these are just the new features. There are also 21 bug fixes and 47 updates. Lots of those updates introduce new features too but in a non-invasive (to the API) way.

Containers

Felipe has been working on implementing Containers into the core API. These are their own special kind of Game Object that can support having children. Modify the container and the children are all updated immediately. A lot of effort has been spent ensuring that the process of merely adding containers into the API didn't adversely affect anything else. For those of you who don't need to use them, we were adamant that you shouldn't have to pay any processing cost for making that choice. Only those who actively create containers will get the overhead required to process them added to their games. This took quite a bit of research. However, we're now happy they are working and rendering correctly as you can see in the demo below.

image

Containers support any type of rendering Game Object as a child, including other Containers. If the Container is on the root display list (i.e. not nested within another) then you can apply a Bitmap Mask to it and it'll mask the Container and all its children.

If you would like to experiment with Containers you can checkout the containers branch of the Phaser repo. Once Phaser 3.4 is released we will merge this branch into master ready for version 3.5, which is estimated to be a couple of weeks away.

I've seen a lot of people asking about Scenes. What they are, how to use them and how to get two scenes to talk together. In this tutorial, I'm going to cover all of these topics. This tutorial will also be published to the Phaser website, but for now, newsletter readers get it exclusively. There's a lot of information coming up, so get comfy and settle in.

What is a Scene?

In Phaser 2 there was the concept of a Game World and States. A State allowed you a view into the Game World and only one State could ever be running at once. The State had access to all kinds of systems, such as a Camera, Tweens and the Game Object Factory. When you used a command like this.add from within a State, you were talking to the global Game Object Factory. Once you were done with a State you moved to the next one. States were often split up into logical sections, such as a Preloader State, a Main Menu State and so on.

In Phaser 3 we changed our approach to this entirely. The first change was that States were renamed to Scenes. This was to avoid ambiguity with 'state machines', which are commonly used in games. The global State Manager was also replaced with a Scene Manager. The changes were not just in the naming of the classes though, they run much deeper than this.

Rather than Phaser managing one 'Game World' there is now no World object at all. Instead of Scenes just having references to all of the systems that the Phaser.Game instance owns, they now own them themselves. You can think of Scenes as being almost entirely self-contained Game Worlds in their own right. They manage their own input, tweens, game objects, display list, cameras and more. A Tween created in Scene A is completely separate to one created in Scene B.

Scenes now control everything using their own instances of plugins. In fact, the only thing that the Game itself is responsible for is passing on global DOM-based events to the Scenes, such as when to update (from RequestAnimationFrame) or core input events from the Input Manager. The handling of these events is done by the Scenes themselves though.

What does Game still control?

There are a few systems which are inherently global in their nature and therefore belong to the Game instance. These are:

▪ The Renderer. There is only one instance of either the Canvas or WebGL Renderer per Game, and it's a property of the Game object.
▪ The Animation Manager. Animations in Phaser 3 are global and no longer bound to a specific Game Object. You can create many different animations, which are all stored in the Animation Manager, and then any Game Object, in any Scene, can use them without duplicating lots of data and wasting memory.
▪ The Cache. When files are loaded by a Scene they are placed into a global cache. So if Scene A loads an XML file, that XML data can be retrieved by any Scene as the cache is global.
▪ The Registry. Every Scene has its own instance of the DataManager, but the Game also has one which you can reference from a Scene via the property registry. This allows for easy cross-Scene data exchange (as we'll see later in this guide)
▪ The Input Manager. The Input Manager does very little in Phaser 3. It just monitors and processes DOM-level input events, such as those raised from pointers, gamepads or the keyboard. Every Scene has its own Input Plugin, which is what does all of the real work with the events, and is what you interface with when calling this.input from a Scene.
▪ The Scene Manager. Responsible for creating, managing and updating all of the Scenes in your game.
▪ The Device Inspector. Allows you to poll for features supported by the browser and hardware your game is running on. The Device class is actual a singleton and only runs once per browser, so isn't directly bound to your Game instance (i.e. if you had 2 game instances running on the same page, they would share the global Device inspector)
▪ The Sound Manager. Like rendering, sounds are managed by a global system in Phaser 3. You can create Sound objects, markers, and so on from your Scenes, but there is only one manager running at once to avoid resource allocation issues.
▪ The TimeStep. This plugin manages the Request Animation Frame loop and updates the core Game, causing it to step. You rarely need to interact with this directly.
▪ The Renderer. There is only one instance of either the Canvas or WebGL Renderer per Game, and it's a property of the Game object. ▪ The Animation Manager. Animations in Phaser 3 are global and no longer bound to a specific Game Object. You can create many different animations, which are all stored in the Animation Manager, and then any Game Object, in any Scene, can use them without duplicating lots of data and wasting memory. ▪ The Cache. When files are loaded by a Scene they are placed into a global cache. So if Scene A loads an XML file, that XML data can be retrieved by any Scene as the cache is global. ▪ The Registry. Every Scene has its own instance of the DataManager, but the Game also has one which you can reference from a Scene via the property registry. This allows for easy cross-Scene data exchange (as we'll see later in this guide) ▪ The Input Manager. The Input Manager does very little in Phaser 3. It just monitors and processes DOM-level input events, such as those raised from pointers, gamepads or the keyboard. Every Scene has its own Input Plugin, which is what does all of the real work with the events, and is what you interface with when calling this.input from a Scene. ▪ The Scene Manager. Responsible for creating, managing and updating all of the Scenes in your game. ▪ The Device Inspector. Allows you to poll for features supported by the browser and hardware your game is running on. The Device class is actual a singleton and only runs once per browser, so isn't directly bound to your Game instance (i.e. if you had 2 game instances running on the same page, they would share the global Device inspector) ▪ The Sound Manager. Like rendering, sounds are managed by a global system in Phaser 3. You can create Sound objects, markers, and so on from your Scenes, but there is only one manager running at once to avoid resource allocation issues. ▪ The TimeStep. This plugin manages the Request Animation Frame loop and updates the core Game, causing it to step. You rarely need to interact with this directly.Everything else, such as Tweens, Physics, Game Objects and Input handling are all managed through Scene level plugins. The Game is now only used for the timestep and the systems that are truly global, which wouldn't have made sense to duplicate per Scene.

What happens when you create a Scene

There are lots of different ways to create a Scene but the fundamental approach is the same in all of them. A Scene consists of a Scene Configuration object and a bunch of functions. Here we'll create an example Scene using an ES6 approach:

image

We extend the Phaser.Scene object and give it a unique key (in this case MyFirstScene) in the constructor. There are two methods: preload and create. The first loads an image, the second displays it. You don't have to have a preload method, the only requirement to be a valid Scene is a create method as this is the global entry-point of all Scenes in Phaser 3.

Here is the exact same thing using ES5:

image

Creating the Scene on its own isn't enough though, it also needs to be added to the Game. You can do this when the Game is created, using the game config like this:

image

The Scene has been passed in via the scene property. This can also be an array of Scenes if you have more than one. This is exactly the same regardless of ES5 or ES6.

If you've looked at any of the Phaser 3 examples you'll probably have seen a completely different method of creating a Scene that looks more like this:

image

So hang on a minute, in the ES6 and ES5 Scenes we passed an instance of them in the game config, but in the above code we're passing an actual object with just a couple of properties (preload and create) instead.

The reason this works is that, internally, the Scene Manager does a lot to determine what's being given to it.

First it looks at the scene property of the game config. If it's an array it then iterates through it, processing each entry in turn, otherwise it just processes the first entry found. It inspects each item given to it to see what type it is, i.e. a class, an object or a prototype function, and then turns them into full Scene objects, adding them into the Scene Manager.

Ultimately, it doesn't matter which approach you use to define your Scene, once the Scene Manager is done with them they're all treated the same internally anyway. And it's when they get turned into full Scenes that they gain several important additions such as the Scene Settings and Systems, plus the ability to communicate with each other.

Scene Settings

When your Scene is created it extracts any settings you may have defined in its config. If there aren't any, it just uses the defaults. Settings are defined in a configuration object passed to the Scene constructor. Here's an example of setting the Scenes name and physics engine from the config:

image

The Settings object can also be used to load files. You should really only use this for loading small files as no progress feedback is ever given to the user. Use the following syntax:

image

The assets are loaded before your Scene Preload method is called.

It's perfect for loading a very small number of graphics, i.e. a background and progress bar image, that your Preloader Scene can then display while loading all the rest of the game assets. Or you could use it to load your internal game config, which could be parsed before loading the rest of the assets.

Scene Systems

When the Scene Manager creates your scene it installs a Scene Systems object into it. This is placed on the property sys, meaning you should never replace or overwrite the property sys in your game code, or very bad things will happen :)

The Scene Systems class is the heart of your Scene. It controls all of the Scene plugins, emits events, lets you to modify the Scene (such as sending it to sleep, waking it up, etc) and allows all of the plugins to communicate with the each other.

It will automatically install 7 Core Plugins into your Scenes:

▪ An Event Emitter
▪ The 2D Camera Manager
▪ The Game Object Creator
▪ The Game Object Factory
▪ The Scene Plugin
▪ The Display List
▪ The Update List
▪ An Event Emitter ▪ The 2D Camera Manager ▪ The Game Object Creator ▪ The Game Object Factory ▪ The Scene Plugin ▪ The Display List ▪ The Update ListAs you can see from the list above, each Scene has its own Display List, factories and Camera system. So when you issue a command like this.add.image you're interfacing directly with the Scene based Game Object Factory, and adding the resulting image to the Scene level display list.

These plugins are non-optional, as they all rely on each other being present. So every Scene has them. However, you can control which are exposed as properties on the Scene objects via the Injection Map.

There are also 7 Default Plugins. These are installed into your Scenes unless you specify otherwise via the Scene config:

▪ The 3D Camera Manager
▪ The Clock
▪ The Data Manager Plugin
▪ The Input Plugin
▪ The Loader Plugin
▪ The Tween Manager
▪ The Lights Plugin
▪ The 3D Camera Manager ▪ The Clock ▪ The Data Manager Plugin ▪ The Input Plugin ▪ The Loader Plugin ▪ The Tween Manager ▪ The Lights PluginThe plugins above are all optional. As with the Core Plugins you can control which ones are exposed via properties using the Injection Map.

Configuring Plugins

Remember that the Core Plugins cannot be removed. To remove all of the Default Plugins you simply have to pass an empty plugins array in your scene config:

image

If you now try and use this.load in your Scene, it will fail, because the Loader Plugin has been excluded from this Scene.

If you want just the Loader and Tween plugin, but none of the others, you can specify just those:

image

If you're not sure which plugins you will need when you create your Scene you can install them via the Scene Systems. This must be done in an init method:

image

The call to install tells it to install the Default Plugin TweenManager, allowing you to add tweens in this Scene.

Scene Injection Map

In Phaser 2 the State Manager would create no less than 19 properties within your State, all linked to global game systems. For example, it would take your State and then add the physics property to it, which mapped to the Physics manager, scale mapped to the Scale Manager, and so on.

This was a double-edged sword. It made Phaser incredibly easy to use. There was no convoluted access required to a system, you literally just typed it out and there it was. However, you had no choice over the quantity or name of the properties that were injected. If you really wanted to use a local property called world you couldn't without literally breaking your game. If you accidentally overwrote one of the 19 default properties, it would also break your game. Experienced devs learned to deal with this but we thought there was a better way for Phaser 3.

To that end, we created a Scene Injection Map. This object controls which plugins are mapped to properties within your Scene, and controls exactly what those properties are called.

By default all of the following properties are installed into a Scene:

'anims' = Animation Manager (Global)
'cache' = Cache (Global)
'game' = Phaser.Game instance (Global)
'registry' = Game Data Manager (Global)
'sound' = Sound Manager (Global)
'textures' = Texture Manager (Global)

'add' = Game Object Factory (Local, Core)
'cameras' = 2D Camera Manager (Local, Core)
'children' = Display List (Local, Core)
'events' = Event Emitter (Local, Core)
'make' = Game Object Creator (Local, Core)
'scene' = Scene Manager Plugin (Local, Core)

The following properties are installed into a Scene only if the respective plugin is available:

'cameras3d' = 3D Camera Manager (Local, Optional)
'data' = Scene Data Manager (Local, Optional)
'impact' = Impact Physics (Local, Optional)
'input' = Input Plugin (Local, Optional)
'lights' = Lights Manager Plugin (Local, Optional)
'load' = Loader Plugin (Local, Optional)
'matter' = Matter JS Physics (Local, Optional)
'physics' = Arcade Physics (Local, Optional)
'time' = Time / Clock Plugin (Local, Optional)
'tweens' = Tween Manager (Local, Optional)

If you prefer you can choose not to have any properties added to your Scene at all:

image

Or you can change the name of the property that is injected using the map object. Here we will replace the English properties with Spanish equivalents:

image

If your IDE supports it, you can even use UTF8, such as this Simplified Chinese version:

image

Cross Talk - Calling a Scene function

Now we know how to create and configure Scenes, let's get them talking to each other. There are several ways to achieve this: Calling a function directly, listening for an event or exchanging data via the registry. We'll cover each now:

Calling a Scene Function

First, we'll create two basic Scenes:

image

Here SceneA listens out for pointer events. When it receives one it calls the clickHandler method. In here we grab a reference to SceneB. This is done using the Scenes key, which is MySecondScene. Once we have that, we can call any public methods which it exposes. In this case we're calling getPosition. This method returns a vec2 with a random location in it. We then add an image at that location.

It's not exactly a complex example, but you should get the idea: Any public function defined on a Scene can be called by any other scene.

image

Listening for Scene Events

In this example instead of calling a function on SceneB directly, we're going to have it listen for events from SceneA. The set-up is the same as before, but our clickHandler is different:

image

Here, when a box is clicked, we dispatch the addScore event. Our SceneB looks like this:

image

It creates a text object to display the score, gets a reference to SceneA and then listens for addScore events from it. When it receives one it updates the local score and Text object.

The advantage to this approach is that SceneA is not tightly coupled to your SceneB. As long as the event names don't change, SceneA can happily sit there, dispatching events as long as it likes, knowing that any other Scenes interested in them will pick them up. However, it does mean that SceneB is coupled to SceneA, as it needs a reference to it in order to listen to its event emitter. We can avoid this entirely by using the Game Registry.

image

Exchange Data via the Game Registry

We're going to expand upon the previous example slightly. This time we will be using the Game Registry, which is an instance of the Data Manager Plugin, in order to exchange data. This is SceneA, our GameScene. It's the same as before, except we tint every other box red. If you click a red box then you lose one of your lives. If you click a normal box, you gain a point:

image

As the boxes are clicked we updated the respective values in the registry using the registry.set call.

Now to SceneB. This Scene is the same as before, except we've added another Text object to display the lives remaining:

image

It listens out for a changedata event from the Registry and invokes the updateData method if it receives one. This method is set 3 items: the parent, i.e. the owner of the Data Manager, which in this case is the Game. It then receives the string-based key of the entry that was changed, and then finally the new value of this entry.

image

By checking the key we can tell if it was the score or the lives that were changed and update our text objects respectively.

As you can see, using the Game Registry gives us a fully decoupled method of communication between multiple Scenes.

In the next tutorial we will look at the visual aspects of Scenes - changing their position on the scenes list, and how to make them sleep and wake.