Talking about Game development, HTML5, Javascript and Phaser.
During these days I am using Phaser for a series of projects, and one feature I found really interesting is state management.
How can we use Phaser states in game development? Basically, if you divide a game into “blocks”, such as splash screen, main menu, the game itself and so on, each of these “blocks” can be developed as a state.
Nothing you can’t do with just plain coding, but if you consider states management flushes the memory, releases resources, removes listeners and manages garbage collection, you will definitively want to use them in your games.
Before the tutorial starts, I want you to play this little game:
The concept is very simple: there’s a random number from 0 to 9 on the screen, and you have to guess if next number drawn will be higher or lower than the number currently displayed.
Each time you guess right you get one point, and the first time you fail, it’s game over and you will see the score. My best score is 12, for your information.
Now, let’s dissect the game:
As you can see there’s a preloading bar, then a menu screen, then the game itself and the game over screen which calls once again the game itself.
Each of these screens will be represented as a state, so our game will have four states + one special state you will meet in a matter of minutes.
Let’s see the content of index.html file:
<!doctype html> <html> <head> <script src="phaser.min.js"></script> <script src="src/boot.js"></script> <script src="src/preload.js"></script> <script src="src/gametitle.js"></script> <script src="src/thegame.js"></script> <script src="src/gameover.js"></script> <style> body{margin:0} </style> <script> (function() { var game = new Phaser.Game(320, 480, Phaser.CANVAS, "game"); game.state.add("Boot",boot); game.state.add("Preload",preload); game.state.add("GameTitle",gameTitle); game.state.add("TheGame",theGame); game.state.add("GameOver",gameOver); game.state.start("Boot"); })(); </script> </head> <body> </body> </html>
This is quite easy, first we load phaser library:
<script src="phaser.min.js"></script>
then all the files where states code is stored
<script src="src/boot.js"></script> <script src="src/preload.js"></script> <script src="src/gametitle.js"></script> <script src="src/thegame.js"></script> <script src="src/gameover.js"></script>
I saved each state in a separate file. This is not strictly needed, but it will keep your code more organized and reusable. Notice we have five files, just like the four states + one special state.
States declaration is made by game.state.add
: the first argument is the name of the state, while the second is the name of the function to call inside such state.
game.state.add("Boot",boot); game.state.add("Preload",preload); game.state.add("GameTitle",gameTitle); game.state.add("TheGame",theGame); game.state.add("GameOver",gameOver);
Finally, we launch the initial state, Boot, with game.state.start
game.state.start("Boot");
Since Boot state is the first state we are calling, let’s have a look at boot.js:
var boot = function(game){ console.log("%cStarting my awesome game", "color:white; background:red"); }; boot.prototype = { preload: function(){ this.game.load.image("loading","assets/loading.png"); }, create: function(){ this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; this.scale.pageAlignHorizontally = true; this.scale.setScreenSize(); this.game.state.start("Preload"); } }
Boot is our special state: it just adjusts stage size and scale. If you notice, its behavior is not different than a Phaser game: it features preload
and create functions
. At this time, I am only preloading the loading bar image. Once everything is ready, we pass to Preload state, so here we go with preload.js:
var preload = function(game){} preload.prototype = { preload: function(){ var loadingBar = this.add.sprite(160,240,"loading"); loadingBar.anchor.setTo(0.5,0.5); this.load.setPreloadSprite(loadingBar); this.game.load.spritesheet("numbers","assets/numbers.png",100,100); this.game.load.image("gametitle","assets/gametitle.png"); this.game.load.image("play","assets/play.png"); this.game.load.image("higher","assets/higher.png"); this.game.load.image("lower","assets/lower.png"); this.game.load.image("gameover","assets/gameover.png"); }, create: function(){ this.game.state.start("GameTitle"); } }
This function is the actual game preloader, and as you can see all graphic assets are preloaded now. The only interesting feature is that at preloading time I am also placing on the stage the loading bar previously loaded in Boot state:
var loadingBar = this.add.sprite(160,240,"loading"); loadingBar.anchor.setTo(0.5,0.5); this.load.setPreloadSprite(loadingBar)
With load.setPreloadSprite
method, Phaser will act like the sprite we passed as argument was an actual loading bar, setting its width longer as the preloading goes on.
Once all assets have been preloaded, it’s time to pass to GameTitle state, located in gametitle.js:
var gameTitle = function(game){} gameTitle.prototype = { create: function(){ var gameTitle = this.game.add.sprite(160,160,"gametitle"); gameTitle.anchor.setTo(0.5,0.5); var playButton = this.game.add.button(160,320,"play",this.playTheGame,this); playButton.anchor.setTo(0.5,0.5); }, playTheGame: function(){ this.game.state.start("TheGame"); } }
Now the game title has been placed, along with a “play” button that once pressed jumps to TheGame, located in thegame.js:
var theGame = function(game){ spriteNumber = null; number = 0; workingButtons = true; higher = true; score = 0; } theGame.prototype = { create: function(){ number = Math.floor(Math.random()*10); spriteNumber = this.game.add.sprite(160,240,"numbers"); spriteNumber.anchor.setTo(0.5,0.5); spriteNumber.frame = number; var higherButton = this.game.add.button(160,100,"higher",this.clickedHigher,this); higherButton.anchor.setTo(0.5,0.5); var lowerButton = this.game.add.button(160,380,"lower",this.clickedLower,this); lowerButton.anchor.setTo(0.5,0.5); }, clickedHigher: function(){ higher=true; this.tweenNumber(true); }, clickedLower: function(){ higher=false; this.tweenNumber(false); }, tweenNumber: function(higher){ if(workingButtons){ workingButtons=false; var exitTween = this.game.add.tween(spriteNumber); exitTween.to({x:420},500); exitTween.onComplete.add(this.exitNumber,this); exitTween.start(); } }, exitNumber: function(){ spriteNumber.x = -180; spriteNumber.frame = Math.floor(Math.random()*10); var enterTween = this.game.add.tween(spriteNumber); enterTween.to({x:160},500); enterTween.onComplete.add(this.enterNumber,this); enterTween.start(); }, enterNumber: function(){ workingButtons=true; if((higher && spriteNumber.frame<number)||(!higher && spriteNumber.frame>number)){ this.game.state.start("GameOver",true,false,score); } else{ score++; number = spriteNumber.frame; } } }
And now it should be clear how states work, explaining how the game itself works is beyond the scope of this post, but I want you to focus on the way I am calling GameOver state:
this.game.state.start("GameOver",true,false,score);
This is the first time I am calling the state with all its arguments, so let’s have a look at them:
GameOver is the name of the state to start
the second argument is called clearWorld, default at true, and clears the World display list fully (but not the Stage, so if you’ve added your own objects to the Stage they will need managing directly).
the third argument is called clearCache, default at false, and clears all loaded assets. You won’t use it that often as we want to keep loaded assets.
all other parameters from the fourth are variables that will be passed to the init function (if it has one). So I am going to pass the score to GameOver state, have a look at gameover.js:
var gameOver = function(game){} gameOver.prototype = { init: function(score){ alert("You scored: "+score) }, create: function(){ var gameOverTitle = this.game.add.sprite(160,160,"gameover"); gameOverTitle.anchor.setTo(0.5,0.5); var playButton = this.game.add.button(160,320,"play",this.playTheGame,this); playButton.anchor.setTo(0.5,0.5); }, playTheGame: function(){ this.game.state.start("TheGame"); } }
Do you see init
function?
init: function(score){ alert("You scored: "+score) }
That’s how I print out (actually I alert) the score.
And that’s all with the states, hope you will use them in your next project as they are really useful. And obviously you can download the source code of the entire project to study it.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.