Creating the game “Snake” with Phaser

March 13, 2015

For a long time I’ve been meaning to try out Phaser. I’ve so far always built my own game engines, everything from rendering engine, physics, animations and controllers, but this time I wanted to see how it is on the other side, where you’re only bothered with building the actual game mechanics.

I decided to keep my first phaser game really simple. And what’s more simple than the original Snake game?

Phaser is pretty neat, it’s simple to setup and it uses a canvas for the rendering. The game supports different states, i.e. different “pages” (preloader, menu, game, highscore, etc.). This was the first thing I wanted to look at. I created a simple wrapper for a state, an object that contains the methods that are needed, preload(), create(), update(). Here’s an example version of such a state.

The getting started guide has these states hard-coded in the initializer, this, however, is something I didn’t want to do, mostly because I’m lazy, and secondly because I didn’t know how many states I wanted.

I’ve since long used a namespace function for my javascript, where every class is put into an object, it’s a pretty simple namespace handler, it just checks if a namespace exists, if it doesn’t, it creates an object with the path of the namespace.

Anyway, all my states are stored in Snake.States.*, so in order to automatically load the states, I only loop through the objects in that namespace. I’ve added an isStart property on the state that I want to boot from.

this.loadStates = function() {
    var start = false;
    for(var i in Snake.States) {
        if(!Snake.States.hasOwnProperty(i)) {
            continue;
        }
        var state = new Snake.States[i](this.phaser);
        this.phaser.state.add(i,state);
        if(state.isStart) {
            start = i;
        }
    }

    this.phaser.state.start(start);
};
This is from the file Snake.Core.

So now I’ve got the engine up and running. Next I started tackling the actual game building, for the most part, snake is a pretty simple game, the only thing I had to actually think about was how the snake itself should work. In snake, once it eats a “point”, it should grow by one unit longer, so I decided to treat the snake as an array of units.

this.increaseLength = function() {
	// Default start position
	var x = 160;
	var y = 160;

	// Override default start position if it's no this.snake[0], i.e. the head.
	if(this.snake.length != 0) {
		x = this.snake[this.snake.length-1].x + 16;
		y = this.snake[this.snake.length-1].y + 16;
	}

	// Create a unit
	var unit = this.phaser.add.sprite(x, y, 'unit-texture');
	this.phaser.physics.arcade.enable(unit);

	this.snake.push(unit);
}

The first unit is the head, I decided that the easiest way to build the rest of the snake is by just moving the other units after the head, in other words, the head takes one step forward, unit 2 of the snake moves to the heads previous position, unit 3 moves to unit 2’s old position, and on it goes until the complete snake has taken one step forward.

snake
Multiple 90-degree angles on the snake.

This also deals with the 90-degree angle problem (when the snake turns, the turn should be visible until the snake has moved past that position). Anyway, here’s a short version of how I move the snake, or each individual unit of the snake.

var oldX, oldY;
for(var i = 0; i < this.snake.length; i++) {
	var x = this.snake[i].x;
	var y = this.snake[i].y;
	// this.snake[0] would be the head of the snake
	if(i != 0) {
		this.snake[i].x = oldX;
		this.snake[i].y = oldY;
	}

	oldX = x;
	oldY = y;
}

In the original snake game, the snake moves forward by one whole unit per time, phaser on the other hand animates an object forward at 60 fps, one unit is 16px, this would end up being 960px per second (note: you can animate an object forward with velocity, but in this instance I didn’t want to animate the movement, but actually “jump” each unit one length forward).

I wanted to stay true to the game, and since the FPS is handled internally in phaser, I couldn’t just change the refresh rate on the canvas. Instead I opted for a semi-hack to slow the game down to 10 FPS, and during each frame, the snake moves forward by 16 pixels.

this.update = function() {
	if((this.getTimeStamp() - this.lastUpdate) < 100) {
		return;
	}

	this.lastUpdate = this.getTimeStamp(); // Returns current timestamp in ms.

    // Rest of code
}

At this point I have a semi working game, I have a snake that moves and in the correct frame rate. The only thing left is collision detection, both with a “point” and the snake itself. Seeing as the snake always follows the head, I decided to only implement collision detection on the head itself. In the main update function I test if the head is at the same position as a “point”, if so, this.increaseLength() and then I check if the head is at the same position as any of the other units, and if it is, I just end the game.

The complete game took less than three hours to get working, and that’s mostly because I didn’t have to care about anything but the game itself (and reading up a bit on the documentation on phaser). My next game will definitely be built on phaser.

Here’s the github repository with all the code, and here’s the playable version of the game, enjoy!

Tags