Understanding signal dispatch with 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);
     }
}
All it does is to create a myVar property, assign it “hello world” string then prompt it on the console. If you run the script, you will see: 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.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers