Getting Classy with Phaser!

Javascript Classes

I feel like I’ve been living under a rock!

Javascript classes have been around for over a year now! This changes everything! Let me explain.

Over the last 16 years, most of my game making time was spent using Flash. One of the nice things about Flash’s Actionscript language was that it was very well structured. You could use classes, extend other classes and break down things into nice manageable parts. One of my biggest objections to moving to html5 was the lack of classes. We could always fake a class in javascript by using something like:

function Apple (type) {
    this.type = type;
    this.color = "red";
}
 
Apple.prototype.getInfo = function() {
    return this.color + ' ' + this.type + ' apple';
};

var myApple=new Apple("macintosh");
console.log(myApple.getInfo());

Now, this worked perfectly well. The problem was mostly one of being able to organize. I’ve continued to write this way, or I’ve used functions to return objects similar to how I did in this post about complex objects.

However, I just found out that we can now use real classes in Javascript. Technically for what I’ve read that this is just “Syntax Sugar” meaning everything works the same in Javascript, but we can write it differently. That is good enough for me. So now we can write the apple class like:

Class Apple
{
 constructor(type)
 {
    this.type=type;
    this.color=red;
 }
 getInfo()
 {
   return this.color + ' ' + this.type + ' apple';
 }
}

var myApple=new Apple("macintosh"); 
console.log(myApple.getInfo());

Using Classes in Phaser

Now, what does this mean for Phaser?

It means that we can:

  • write classes that extend Phaser’s classes
  • write much more reusable code
  • organize out code more efficiently

Making a grid!

For example, a lot of my games and projects need a grid. The grid needs to have objects added to it, and then arrange the objects in rows and columns. Now in Phaser, I would use a group for this, add each object to the group and then loop through the group using forEach. I do this so I’d like to write a class that I can just copy into my project folder whenever I need to use a grid.

So first I need to make a class named Grid.

class Grid {
    constructor() {
    	
    }
}

The second step is to make the Grid class extend Phaser’s group class. We can do this by using the extends keyword.

Phaser’s group class will be the parent of our Grid class.

class Grid extends Phaser.Group {
    constructor() {    	
    	
    }
    }

The last step is to call the constructor of the parent(Phaser.Group) by using the super command and passing the instance of the game as a parameter. This is assuming you are running the code inside a phaser game, named “game”. Make sure that super is the first thing called inside the constructor.

class Grid extends Phaser.Group {
    constructor() {
    	super(game);   
    }
    }

Right now our grid doesn’t do anything more that a Phaser group. So why go to this trouble? Because now we can add in our own custom functions and variables!

Let’s start by passing in a parameter to the constructor named “cols” to represent the number of columns we want the grid to have and then setting that to a class variable.

class Grid extends Phaser.Group {
    constructor(cols) {
    	super(game);   
    	this.cols=cols;
    }
    }

After adding the items, we need to arrange them in a grid so let’s make that function now. Note: This will only work well with items that are the same size.

arrange()
    {
    	//current row count
    	var row=0;
    	//current column count
    	var col=0;
    	//use the group's built in for each to loop
    	//through all the children
    	this.forEach(function(item)
    	{
    		//set the position based
    		//on the row, the column
    		//and the height of the item
    		item.y=row*item.height;
    		item.x=col*item.width;

    		//advance the column count
    		col++;
    		//if the column count is equal to the 
    		//number of columns set
    		if (col==this.cols)
    		{
    			//go to the next row
    			row++;
    			//reset the column to 0
    			col=0;
    		}
    	}.bind(this));
    	//use bind(this) to keep the 'this' keyword
    	//to mean the class
    }

Now you can use the grid class like this:

var grid=new Grid(3);
//add nine sprites
grid.add(sprite1);
....
grid.add(sprite9);
grid.arrange();

What about extending a sprite?

It takes a little more work, but it can be done like this:

class LetterBox extends Phaser.Sprite {
    constructor() {
    	super(game,0,0,"letters",0);

    	//add to stage right away
    	game.add.existing(this);
    }
    }

In the super constructor for the sprite, the parameters are

super(game,x,y,"library_key",frame_number);

The game.add.existing will add the sprite to the stage right away after calling

var letter=new LetterBox();

If you are planning on adding the instance of the class to a group, you can omit it.

Here is an example of using the Grid and LetterBox classes together with a few extra functions added.

StateMain.js

var StateMain = {
    preload: function() {
        //preload the sprite sheet
        game.load.atlasJSONHash('letters', "images/letters.png", "images/letters.json");
    },
    create: function() {
        //make a new grid 
        //with 5 columns
        //
        var grid = new Grid(5);
        //
        //make 25 letter boxes
        //
        for (var a = 0; a < 25; a++) {
            //
            //make a new letter box
            //
            var lb = new LetterBox();
            //
            //set a random letter
            //
            lb.setRand();
            //
            //add the letter to the grid
            //
            grid.add(lb);
        }
        //arrange the grid
        grid.arrange();
        //fit to the stage
        grid.fitStage();
        //put the grid in the center
        grid.center();
    },
    update: function() {}
}

The Grid Class – grid.js

class Grid extends Phaser.Group {
    constructor(cols) {
        super(game);
        this.cols = cols;
    }
    arrange() {
        //current row count
        var row = 0;
        //current column count
        var col = 0;
        //use the group's built in for each to loop
        //through all the children
        this.forEach(function(item) {
            //set the position based
            //on the row, the column
            //and the height of the item
            item.y = row * item.height;
            item.x = col * item.width;
            //advance the column count
            col++;
            //if the column count is equal to the 
            //number of columns set
            if (col == this.cols) {
                //go to the next row
                row++;
                //reset the column to 0
                col = 0;
            }
        }.bind(this));
        //use bind(this) to keep the 'this' keyword
        //to mean the class
    }
    fitStage(per = 100) {
        this.width = game.width * (per / 100);
        this.scale.y = this.scale.x;
    }
    center() {
        this.x = game.width / 2 - this.width / 2;
        this.y = game.height / 2 - this.height / 2;
    }
}

The Letter Box Class – letterBox.js

class LetterBox extends Phaser.Sprite {
    constructor() {
        super(game, 0, 0, "letters", 0);
        //add to stage right away
        //game.add.existing(this);
    }
    /**
     * set by passing a lower case letter
     */
    setLetter(letter) {
        var index = letter.charCodeAt(0);
        this.frame = index - 97;
    }
    /**
     * set a random letter
     */
    setRand() {
        var index = game.rnd.integerInRange(0, 26);
        this.frame = index;
    }
}

1 thought on “Getting Classy with Phaser!”

Leave a Comment