Talking about HTML5, Javascript and Phaser.
One interesting Phaser feature which people do not talk about that much is signal dispatch. A Signal is an event dispatch mechanism that supports broadcasting to multiple listeners. Signals aren’t that different from plain JavaScript events, but signals can also pass arguments. In this basic guide we’ll see how to use signals in the simplest way possible. We will also see some concepts about context. Let’s see this small script:
var game;
window.onload = function() {
game = new Phaser.Game(480, 640, Phaser.AUTO, "");
game.state.add("PlayGame", playGame);
game.state.start("PlayGame");
}
var playGame = function(game){};
playGame.prototype = {
create: function(){
this.myVar = "hello world";
console.log(this.myVar);
}
}
hello world
What happens if the same console.log
line is executed inside a callback function, for example after an input?
var game; window.onload = function() { game = new Phaser.Game(480, 640, Phaser.AUTO, ""); game.state.add("PlayGame", playGame); game.state.start("PlayGame"); } var playGame = function(game){}; playGame.prototype = { create: function(){ this.myVar = "hello world"; game.input.onDown.add(function(){ console.log(this.myVar) }) } }Now
myVar
content is lost, we can’t retrieve it when we click or tap:
undefined
This happens because we lost the context once we enter the callback function. That’s why Phaser allows us to pass the context next to the callback function, this way:
var game; window.onload = function() { game = new Phaser.Game(480, 640, Phaser.AUTO, ""); game.state.add("PlayGame", playGame); game.state.start("PlayGame"); } var playGame = function(game){}; playGame.prototype = { create: function(){ this.myVar = "hello world"; game.input.onDown.add(function(){ console.log(this.myVar) }, this) } }And now we can access again to
myVar
value if we click or tap:
hello world
Now, let’s create a class, the most basic class ever, which only prompts some text on the console:
var game; window.onload = function() { game = new Phaser.Game(480, 640, Phaser.AUTO, ""); game.state.add("PlayGame", playGame); game.state.start("PlayGame"); } var playGame = function(game){}; playGame.prototype = { create: function(){ this.myVar = "hello world"; game.input.onDown.add(function(){ console.log(this.myVar) }, this); var newClass = new NewClass(game); } } NewClass = function (game) { console.log("I am a new class") }; NewClass.prototype.constructor = NewClass;As you can see the text is appearing on the console, followed by
myVar
content each time we click or tap:
I am a new class
hello world
Now, let’s change things a bit and create a writeMyVar
method which simply outpus myVar
value, then call it:
var game; window.onload = function() { game = new Phaser.Game(480, 640, Phaser.AUTO, ""); game.state.add("PlayGame", playGame); game.state.start("PlayGame"); } var playGame = function(game){}; playGame.prototype = { create: function(){ this.myVar = "hello world"; game.input.onDown.add(function(){ console.log(this.myVar) }, this); var newClass = new NewClass(game); this.writeMyVar(); }, writeMyVar: function(){ console.log("from the function: " + this.myVar); } } NewClass = function (game) { console.log("I am a new class") }; NewClass.prototype.constructor = NewClass;Once you execute the code, we have the messages properly displayed on the console:
I am a new class
from the function: hello world
Problems start when you try to access PlayGame context from inside the new class, trying with a playGame.prototype.writeMyVar();
:
var game; window.onload = function() { game = new Phaser.Game(480, 640, Phaser.AUTO, ""); game.state.add("PlayGame", playGame); game.state.start("PlayGame"); } var playGame = function(game){}; playGame.prototype = { create: function(){ this.myVar = "hello world"; game.input.onDown.add(function(){ console.log(this.myVar) }, this); var newClass = new NewClass(game); this.writeMyVar(); }, writeMyVar: function(){ console.log("from the function: " + this.myVar); } } NewClass = function (game) { console.log("I am a new class"); playGame.prototype.writeMyVar(); }; NewClass.prototype.constructor = NewClass;That’s right, we get an
undefined
:
I am a new class
from the function: undefined
from the function: hello world
Obviously there are workarounds to fix this, but now it’s time to introduce signals, here is the final script:
var game; window.onload = function() { game = new Phaser.Game(480, 640, Phaser.AUTO, ""); game.state.add("PlayGame", playGame); game.state.start("PlayGame"); } var playGame = function(game){}; playGame.prototype = { create: function(){ this.myVar = "hello world"; game.input.onDown.add(function(){ console.log(this.myVar) }, this); var newClass = new NewClass(game); newClass.signal.add(this.writeMyVar, this); newClass.sendSignal(); this.writeMyVar(); }, writeMyVar: function(){ console.log("from the function: " + this.myVar); } } NewClass = function (game) { console.log("I am a new class"); this.signal = new Phaser.Signal(); }; NewClass.prototype.constructor = NewClass; NewClass.prototype.sendSignal = function() { this.signal.dispatch(); }And the first thing I am showing you is the script is working:
I am a new class
from the function: hello world
from the function: hello world
Now let’s see the new lines:
Line 17: signal
is a NewClass property which is declared at line 28. In this step, we add as callback function writeMyVar
method, with this
context.
Line 18: We call sendSignal
method of NewClass
. As you will see, this method only dispatches a signal. In this example we call it manually from the code, in a real world example inside NewClass the signal can be dispatched when a coin is collected / an enemy is killed and so on.
Line 28: this is how we create a new signal.
Line 33: declaration of sendSignal
method.
Line 34: finally here is how we dispatch a signal.
And now you should be able to improve the example using the full options available in the official documentation. A real world example which uses signals in an actual game will come in a few days. Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.