Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Hero Slide game, Game development, HTML5, Javascript and Phaser.

Did you enjoy the first step of Hero Slide prototype made with Phaser? Time to proceed to next step, you already know how to: * Initialize the game * Place random tiles on the map * Move tiles with WASD keys And now you’ll see these new features: * Add animation to tile creation and movement * Match tiles The game matches two tiles when the player tries to move two adjacent tiles of the same kind in a direction but they both can’t move, in this case similar tiles will slide one over the other, popping one slide, freeing the game field and allowing you to keep playing. I really suck when it’s time to explain game mechanics, so you’d better have a look at the original iOS game. Now, play the game with WASD key – focus the canvas first.
As you can see, animations make the game look smoother and you can match tiles. And this is the commented source code, with new lines highlighted:
// the game
var game;

// size of each tile, in pixels
var tileSize = 120;

// different kinds of tiles
var tileTypes = 5;

// the game array, the board will be stored here
var gameArray = [];

// field size, in tiles. This will represent a 4x4 tiles field
var fieldSize = 4;

// creation of the game
window.onload = function() {	
	game = new Phaser.Game(480, 480);
     game.state.add("PlayGame", playGame);
     game.state.start("PlayGame");
}


var playGame = function(game){}


playGame.prototype = {
     preload: function(){
          
          // preloading the assets
          game.load.spritesheet("tiles", "tiles.png", tileSize, tileSize);          
     },
     create: function(){ 
          
          // initializing game board
          for(var i = 0; i < fieldSize; i++){
               gameArray[i] = [];
               for(var j = 0; j < fieldSize; j++){
                    
                    // each array item is an object with a tile value (0: empty) and a sprite (null: no sprite)
                    gameArray[i][j] = {
                         tileValue : 0,
                         tileSprite: null
                    };
               }
          }
          
          // function to add a new item, will be explained later
          this.addItem(); 
          
          // liteners to handle WASD keys. Each key calls handleKey function
          this.upKey = game.input.keyboard.addKey(Phaser.Keyboard.W);
          this.upKey.onDown.add(this.handleKey, this);
    		this.downKey = game.input.keyboard.addKey(Phaser.Keyboard.S);
    		this.downKey.onDown.add(this.handleKey, this);
    		this.leftKey = game.input.keyboard.addKey(Phaser.Keyboard.A);
    		this.leftKey.onDown.add(this.handleKey, this);
    		this.rightKey = game.input.keyboard.addKey(Phaser.Keyboard.D);
    		this.rightKey.onDown.add(this.handleKey, this);    
     },
     
     // this function will add a new item to the board
     addItem: function(){
     
          // emptySpots is an array which will contain all the available empty tiles where to place a new item
          var emptySpots = [];
          
          // now we loop through the game board to check for empty tiles
          for(var i = 0; i < fieldSize; i++){
               for(var j = 0; j < fieldSize; j++){
               
                    // remember we define an empty tile as a tile whose tileValue is zero
                    if(gameArray[i][j].tileValue == 0){
                    
                         // at this time we push a Point with tile coordinates into emptySpots array
                         emptySpots.push(new Phaser.Point(j, i));
                    }
               }
          }
          
          // newSpot is a randomly picked item in emptySpots array
          var newSpot = Phaser.ArrayUtils.getRandomItem(emptySpots);
          
          // if newSpot is not null this means we have a place where to put a new tile
          if(newSpot != null){
          
               // selecting a random value between 1 and tileTypes
               var tileType = game.rnd.between(1, tileTypes);
               
               // updating game array with the new tile value and sprite
               gameArray[newSpot.y][newSpot.x] = {
                    tileValue: tileType,
                    tileSprite: game.add.sprite(newSpot.x * tileSize, newSpot.y * tileSize, "tiles", tileType - 1)
               }
               
               // we start with the alpha at zero to create a "fade in" tween
               gameArray[newSpot.y][newSpot.x].tileSprite.alpha = 0;
               
               // here is the fade in effect
               var fadeTween = game.add.tween(gameArray[newSpot.y][newSpot.x].tileSprite).to({
                    alpha: 1
               }, 500, Phaser.Easing.Linear.None, true);
               
               // now the player can move
               fadeTween.onComplete.add(function(e){
                    
                    // the player can move again
                    this.canMove = true;    
               }, this);
          }
     },
     
     // this function handles player movements
     handleKey: function(e){
          
          // first of all, let's see if the player can move
          if(this.canMove){
          
               // if the player can move, let's set canMove to false to prevent the player to move twice
               this.canMove=false;
               
               // time to check for the keycode which generated the event
               switch(e.keyCode){
               
                    // "A" key (left)
                    case Phaser.Keyboard.A:
                         
                         // we scan for game field, from TOP to BOTTOM and from LEFT to RIGHT starting from the 2nd column
                         for(var i = 0; i < fieldSize; i++){
                              for(var j = 1; j < fieldSize; j++){
                              
                                   // we can move a tile if it's not empty and the tile on its left is empty
                                   if(gameArray[i][j].tileValue != 0 && gameArray[i][j - 1].tileValue == 0){
                                        
                                        // moving the sprite on the left
                                        var moveTween = game.add.tween(gameArray[i][j].tileSprite).to({
                                             x: gameArray[i][j].tileSprite.x - tileSize     
                                        }, 200,  Phaser.Easing.Linear.None, true);
                                        
                                        // copying the content of the current tile on the tile on its left
                                        gameArray[i][j - 1] = {
                                             tileValue: gameArray[i][j].tileValue,
                                             tileSprite: gameArray[i][j].tileSprite
                                        }
                                        
                                        //setting current tile to empty
                                        gameArray[i][j] = {
                                             tileValue: 0,
                                             tileSprite: null
                                        }
                                   }
                                   else{
                                        // we can match a tile if it's not empty and the tile on its left has the same value
                                        if(gameArray[i][j].tileValue != 0 && gameArray[i][j - 1].tileValue == gameArray[i][j].tileValue){
                                             
                                             // moving the sprite on the left
                                             var moveTween = game.add.tween(gameArray[i][j].tileSprite).to({
                                                  x: gameArray[i][j].tileSprite.x - tileSize     
                                             }, 200,  Phaser.Easing.Linear.None, true);
                                             
                                             // no need to copy the content of the current tile on the tile on its left, but we are going to remove
                                             // the sprite we won't use any longer once the tween has been completed
                                             moveTween.onComplete.add(function(e){
                                                  e.destroy();   
                                             }, this);
                                             
                                             //setting current tile to empty
                                             gameArray[i][j] = {
                                                  tileValue: 0,
                                                  tileSprite: null
                                             }
                                        }
                                   }
                              }
                         }
                    break;
                    
                    // "W" key (up)
                    case Phaser.Keyboard.W:
                    
                         // we scan for game field, from TOP to BOTTOM and from LEFT to RIGHT starting from the 2nd row
                         // applying the same concepts seen before
                         for(var i = 1; i < fieldSize; i++){
                              for(var j = 0; j < fieldSize; j++){
                                   if(gameArray[i][j].tileValue != 0 && gameArray[i - 1][j].tileValue == 0){
                                        var moveTween = game.add.tween(gameArray[i][j].tileSprite).to({
                                             y: gameArray[i][j].tileSprite.y - tileSize     
                                        }, 200,  Phaser.Easing.Linear.None, true);
                                        gameArray[i - 1][j ] = {
                                             tileValue: gameArray[i][j].tileValue,
                                             tileSprite: gameArray[i][j].tileSprite
                                        }
                                        gameArray[i][j] = {
                                             tileValue: 0,
                                             tileSprite: null
                                        }
                                   }
                                   else{
                                        if(gameArray[i][j].tileValue != 0 && gameArray[i - 1][j].tileValue == gameArray[i][j].tileValue){
                                             var moveTween = game.add.tween(gameArray[i][j].tileSprite).to({
                                                  y: gameArray[i][j].tileSprite.y - tileSize     
                                             }, 200,  Phaser.Easing.Linear.None, true);
                                             moveTween.onComplete.add(function(e){
                                                  e.destroy();   
                                             }, this);
                                             gameArray[i][j] = {
                                                  tileValue: 0,
                                                  tileSprite: null
                                             }
                                        }     
                                   }
                              }
                         }
                    break;
                    
                    // "D" key (right)
                    case Phaser.Keyboard.D:
                    
                         // we scan for game field, from TOP to BOTTOM and from RIGHT to LEFT starting from the next-to-last column
                         // applying the same concepts seen before
                         for(var i = 0; i < fieldSize; i++){
                              for(var j = fieldSize - 2; j >= 0; j--){
                                   if(gameArray[i][j].tileValue != 0 && gameArray[i][j + 1].tileValue == 0){
                                        var moveTween = game.add.tween(gameArray[i][j].tileSprite).to({
                                             x: gameArray[i][j].tileSprite.x + tileSize     
                                        }, 200,  Phaser.Easing.Linear.None, true);
                                        gameArray[i][j + 1] = {
                                             tileValue: gameArray[i][j].tileValue,
                                             tileSprite: gameArray[i][j].tileSprite
                                        }
                                        gameArray[i][j] = {
                                             tileValue: 0,
                                             tileSprite: null
                                        }
                                   }
                                   else{
                                        if(gameArray[i][j].tileValue != 0 && gameArray[i][j + 1].tileValue == gameArray[i][j].tileValue){
                                             var moveTween = game.add.tween(gameArray[i][j].tileSprite).to({
                                                  x: gameArray[i][j].tileSprite.x + tileSize     
                                             }, 200,  Phaser.Easing.Linear.None, true);
                                             moveTween.onComplete.add(function(e){
                                                  e.destroy();   
                                             }, this);
                                             gameArray[i][j] = {
                                                  tileValue: 0,
                                                  tileSprite: null
                                             }
                                        }
                                   }
                              }
                         }
                    break;
                    
                    // "S" key (down)
                    case Phaser.Keyboard.S:
                         
                         // we scan for game field, from BOTTOM to TOP and from LEFT to RIGHT starting from the next-to-last row
                         // applying the same concepts seen before
                         for(var i = fieldSize - 2; i >= 0; i--){
                              for(var j = 0; j < fieldSize; j++){
                                   if(gameArray[i][j].tileValue != 0 && gameArray[i + 1][j].tileValue == 0){
                                        var moveTween = game.add.tween(gameArray[i][j].tileSprite).to({
                                             y: gameArray[i][j].tileSprite.y + tileSize     
                                        }, 200,  Phaser.Easing.Linear.None, true);
                                        gameArray[i + 1][j ] = {
                                             tileValue: gameArray[i][j].tileValue,
                                             tileSprite: gameArray[i][j].tileSprite
                                        }
                                        gameArray[i][j] = {
                                             tileValue: 0,
                                             tileSprite: null
                                        }
                                   }
                                   else{
                                        if(gameArray[i][j].tileValue != 0 && gameArray[i + 1][j].tileValue == gameArray[i][j].tileValue){
                                             var moveTween = game.add.tween(gameArray[i][j].tileSprite).to({
                                                  y: gameArray[i][j].tileSprite.y + tileSize     
                                             }, 200,  Phaser.Easing.Linear.None, true);
                                             moveTween.onComplete.add(function(e){
                                                  e.destroy();   
                                             }, this);
                                             gameArray[i][j] = {
                                                  tileValue: 0,
                                                  tileSprite: null
                                             }
                                        }
                                   }
                              }
                         }
                    break;
                    
               } 
               
               // at the end of player input, we add a new item
               this.addItem();               
          }
     }
}
That’s all at the moment, during next step I will show you how to make bombs explode and how to control game with swipe, meanwhile download the source code.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.