Build a HTML5 game like iOS lovely puzzle game “Warp Shift” using Phaser

Read all posts about "" game
Recently I started playing again Warp Shift by Deep Silver FISHLABS on my iPhone and between a level and another I thought it could be fun to create something similar in HTML5 using Phaser framework. Warp Shift is a unique puzzle game set in a mysterious world. AppSpy says that it “is well-balanced and gorgeous to look at and filled to the brim with innovative twists and new ideas.” It’s not easy to create a detailed tutorial of a game like this one, so we are approaching it step by step. In the first step, this one, we are going to build the engine which will render the first three levels. There’s a precise reason behind this choice: they are the most basic levels, as starting from level 4 new elements are added, and as said we are going step by step. Let me show you the tilesheet used in the prototype:
We have, from left to right, top to bottom: the closed block, the block opened on the top, the block opened on the right, the block opened on the bottom, the block opened to the left, the player and the exit. This is how original levels are rendered: And this is the script capable of doing it:
// the game itself
var game;

// this object contains all customizable game options
// changing them will affect gameplay
var gameOptions = {

    // game width, in pixels
	gameWidth: 400,

    // game height, in pixels
	gameHeight: 400,

     // tile size, in pixels
    tileSize: 100,

    // margin between two tiles, in pixels
    tileMargin: 10
}

// some constants (actually they are variables) where to store tile properties
var UP = 1;
var RIGHT = 2;
var DOWN = 3;
var LEFT = 4;
var EXIT = 5;
var PLAYER = 6;

// function to create a block object
function block(){

    // this is the default block object
    var defaultBlock = {

        // can't walk through top side
        up: false,

        // can't walk through right side
        right: false,

        // can't walk through bottom side
        down: false,

        // can't walk through left side
        left: false,

        // there's no level exit on this block
        exit: false,

        // the player is not on this block
        player: false
    }

    // looping through all function arguments, if any
    for(var i = 0; i < arguments.length; i++){

        // checking the i-th argument
        switch(arguments[i]){

            // if it's UP, then set defaultBlock's "up" key to true
            case UP:
                defaultBlock.up = true;
                break;

            // if it's RIGHT, then set defaultBlock's "right" key to true
            case RIGHT:
                defaultBlock.right = true;
                break;

            // if it's DOWN, then set defaultBlock's "down" key to true
            case DOWN:
                defaultBlock.down = true;
                break;

            // if it's LEFT, then set defaultBlock's "left" key to true
            case LEFT:
                defaultBlock.left = true;
                break;

            // if it's EXIT, then set defaultBlock's "exit" key to true
            case EXIT:
                defaultBlock.exit = true;
                break;

            // if it's PLAYER, then set defaultBlock's "player" key to true
            case PLAYER:
                defaultBlock.player = true;
                break;
        }
    }
    return defaultBlock;
}

var levels = [

    // level 1
    [
        [block(), block(LEFT, EXIT)],
        [block(RIGHT, PLAYER), block()]
    ],

    // level 2
    [
        [block(), block(RIGHT, EXIT)],
        [block(LEFT, PLAYER), block()]
    ],

    // level 3
    [
        [block(), block(UP, PLAYER)],
        [block(DOWN, EXIT), block()]
    ]
]

// function to be execute once the page loads
window.onload = function() {

    // creation of a new Phaser Game
	game = new Phaser.Game(gameOptions.gameWidth, gameOptions.gameHeight);

    // adding "TheGame" state
    game.state.add("TheGame", TheGame);

    // launching "TheGame" state
    game.state.start("TheGame");
}

/* ****************** TheGame state ****************** */

var TheGame = function(){};

TheGame.prototype = {

    // function to be executed when the game preloads
    preload: function(){

        // load the spritesheet with all tiles
        game.load.spritesheet("tile", "assets/sprites/tile.png", gameOptions.tileSize, gameOptions.tileSize);

        // scaling the game to cover the entire screen, while keeping its ratio
        game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;

        // horizontally centering the game
		game.scale.pageAlignHorizontally = true;

        // vertically centering the game
		game.scale.pageAlignVertically = true;

        // set background color
        game.stage.backgroundColor = 0x111111;
    },

    // function to be executed as soon as the game has completely loaded
  	create: function(){

        // we start from level 0
        this.level = 0;

        // this method generates a level
        this.generateLevel();
  	},

    // function to generate a level
    generateLevel: function(){

        // tileAndMargin is the sum of tile and margin size
        var tileAndMargin = gameOptions.tileSize + gameOptions.tileMargin;

        // creation of a group where to place level items
        this.levelGroup = game.add.group();

        // temporary array to store the level so we don't need to modify the original levels
        this.tempLevel = [];

        // looping through level rows
        for(var i = 0; i < levels[this.level].length; i++){

            // preparing the temporary array to store the i-th row
            this.tempLevel[i] = [];

            // looping through level columns
            for(var j = 0; j < levels[this.level][i].length; j++){

                // adding the tile on the stage
                var tile = game.add.image(j * tileAndMargin + gameOptions.tileSize / 2, i * tileAndMargin + gameOptions.tileSize / 2, "tile");

                // set tile registration point to its center
                tile.anchor.set(0.5);

                // adding tile to level group
                this.levelGroup.add(tile);

                // now it's time to assign the tile a frame. If there is no exit, it's frame zero
                if(!levels[this.level][i][j].up && !levels[this.level][i][j].right && !levels[this.level][i][j].down && !levels[this.level][i][j].left){
                    tile.frame = 0;
                }
                else{

                    // if there's an exit on the top, it's frame one
                    if(levels[this.level][i][j].up){
                        tile.frame = 1
                    }

                    // if there's an exit on the right, it's frame two
                    if(levels[this.level][i][j].right){
                        tile.frame = 2;
                    }

                    // if there's an exit on the bottom, it's frame three
                    if(levels[this.level][i][j].down){
                        tile.frame = 3;
                    }

                    // if there's an exit on the left, it's frame four
                    if(levels[this.level][i][j].left){
                        tile.frame = 4;
                    }

                    // if there's the level exit...
                    if(levels[this.level][i][j].exit){

                        // we add the exit tile
                        var exit = game.add.image(0, 0, "tile");

                        // set exit tile registration point to its center
                        exit.anchor.set(0.5);

                        // assign exit tile frame six
                        exit.frame = 6;

                        // set exit tile as a child of current tile
                        tile.addChild(exit);
                    }

                    // if there's the player...
                    if(levels[this.level][i][j].player){

                        // we add the player tile
                        var player = game.add.image(0, 0, "tile");

                        // set player tile registration point to its center
                        player.anchor.set(0.5);

                        // assign player tile frame five
                        player.frame = 5;

                        // set player tile as a child of current tile
                        tile.addChild(player)
                    }
                }

                // now copying original level item into temporary level item
                this.tempLevel[i][j] = {
                    up:  levels[this.level][i][j].up,
                    right: levels[this.level][i][j].right,
                    down: levels[this.level][i][j].down,
                    left: levels[this.level][i][j].left,
                    exit: levels[this.level][i][j].exit,
                    player: levels[this.level][i][j].player,

                    // here we store the tile
                    sprite: tile
                }
            }
        }

        // center the group on the stage
        this.levelGroup.x = (game.width - this.levelGroup.width) / 2;
        this.levelGroup.y = (game.height - this.levelGroup.width) /2;
    }
}
Download the source code and familiarize with it because next time I will show you how to add more complex levels and above all how to add interactivity to the game.

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