Talking about Pyramids of Ra game, Game development, HTML5, Javascript and Phaser.
One month ago I showed you how the HTML5 game engine to create GameBoy blockbuster “Pyramids of Ra” with the first playable level, but the game gets much harder as you progress through the levels, adding new types of tiles. The first new tile you will find is a harder tile which needs the player to cross it twice before disappearing. I placed it on level two of the game, so I am sorry but you have to solve level one before seeing the new tile. You control the grey circle with a swipe, and you have to walk over all white tiles before returning back to start tile (marked with “S”). The problem is tiles fall down once you stepped over them, so mind your moves. Harder tiles are marked in yellow, and will turn white once you cross them the first time, to disappear when you cross them twice. The source code is still uncommented because I need to optimize it a bit, but it’s nothing new if you are used to Phaser.
var game;
// main game options
var gameOptions = {
gameWidth: 1000,
gameHeight: 800,
tileSize: 100,
fieldSize: {
rows: 8,
cols: 10
}
}
// game levels
var levels = [
{
level:[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
],
playerPos: new Phaser.Point(5, 2)
},
{
level:[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
[0, 1, 1, 0, 0, 1, 1, 1, 1, 0],
[0, 1, 1, 3, 3, 1, 1, 1, 0, 0],
[0, 1, 1, 3, 3, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 3, 3, 0, 0],
[0, 0, 0, 0, 0, 0, 3, 3, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
],
playerPos: new Phaser.Point(5, 3)
}
];
//
levelNumber = 0;
// when the window finishes loading...
window.onload = function() {
game = new Phaser.Game(gameOptions.gameWidth, gameOptions.gameHeight);
game.state.add("TheGame", TheGame);
game.state.start("TheGame");
}
var TheGame = function(){};
TheGame.prototype = {
// preloading assets
preload: function(){
game.load.spritesheet("tiles", "assets/sprites/tile.png", gameOptions.tileSize, gameOptions.tileSize);
game.load.image("player", "assets/sprites/player.png");
},
// when the game starts
create: function(){
game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
game.scale.pageAlignHorizontally = true;
game.scale.pageAlignVertically = true;
this.createLevel();
game.input.onDown.add(this.beginSwipe, this);
},
// function to create a level
createLevel: function(){
this.tilesArray = [];
this.tileGroup = game.add.group();
this.tileGroup.x = (game.width - gameOptions.tileSize * gameOptions.fieldSize.cols) / 2;
this.tileGroup.y = (game.height - gameOptions.tileSize * gameOptions.fieldSize.rows) / 2;
for(var i = 0; i < gameOptions.fieldSize.rows; i++){
this.tilesArray[i] = [];
for(var j = 0; j < gameOptions.fieldSize.cols; j++){
if(levels[levelNumber].level[i][j] !=0 ){
this.addTile(i, j, levels[levelNumber].level[i][j]);
}
}
}
this.playerPosition = new Phaser.Point(0, 0);
levels[levelNumber].playerPos.clone(this.playerPosition);
this.player = game.add.sprite(levels[levelNumber].playerPos.x * gameOptions.tileSize + gameOptions.tileSize / 2, this.playerPosition.y * gameOptions.tileSize + gameOptions.tileSize / 2, "player");
this.player.anchor.set(0.5);
this.tileGroup.add(this.player);
this.firstMove = true;
},
// function add a tile at "row" row, "col" column with "val" value
addTile: function(row, col, val){
var tileXPos = col * gameOptions.tileSize + gameOptions.tileSize / 2;
var tileYPos = row * gameOptions.tileSize + gameOptions.tileSize / 2;
var theTile = game.add.sprite(tileXPos, tileYPos, "tiles");
if(val == 3){
theTile.tint = 0xffff88;
}
theTile.anchor.set(0.5);
theTile.tileValue = val;
theTile.falling = false;
theTile.tilePosition = new Phaser.Point(col, row);
this.tilesArray[row][col] = theTile;
this.tileGroup.add(theTile);
},
// start checking for swipes
beginSwipe: function(e){
game.input.onDown.remove(this.beginSwipe, this);
game.input.onUp.add(this.endSwipe, this);
},
// end checking for swipes
endSwipe: function(e){
game.input.onUp.remove(this.endSwipe, this);
var swipeTime = e.timeUp - e.timeDown;
var swipeDistance = Phaser.Point.subtract(e.position, e.positionDown);
var swipeMagnitude = swipeDistance.getMagnitude();
var swipeNormal = Phaser.Point.normalize(swipeDistance);
if(swipeMagnitude > 20 && swipeTime < 1000 && (Math.abs(swipeNormal.x) > 0.8 || Math.abs(swipeNormal.y) > 0.8)){
if(swipeNormal.x > 0.8){
this.handleMovement(new Phaser.Point(1, 0));
}
if(swipeNormal.x < -0.8){
this.handleMovement(new Phaser.Point(-1, 0));
}
if(swipeNormal.y > 0.8){
this.handleMovement(new Phaser.Point(0, 1));
}
if(swipeNormal.y < -0.8){
this.handleMovement(new Phaser.Point(0, -1));
}
}
else{
game.input.onDown.add(this.beginSwipe, this);
}
},
// handling swipes
handleMovement: function(p){
if(this.firstMove){
this.firstMove = false;
this.tilesArray[this.playerPosition.y][this.playerPosition.x].tileValue = 2;
this.tilesArray[this.playerPosition.y][this.playerPosition.x].frame = 1;
}
else{
switch(this.tilesArray[this.playerPosition.y][this.playerPosition.x].tileValue){
case 1:
this.tilesArray[this.playerPosition.y][this.playerPosition.x].falling = true;
var tween = game.add.tween(this.tilesArray[this.playerPosition.y][this.playerPosition.x]).to({
alpha: 0,
width: gameOptions.tileSize / 4,
height: gameOptions.tileSize / 4,
angle: game.rnd.integerInRange(-15, 15)
}, 500, Phaser.Easing.Linear.None, true);
tween.onComplete.add(function(target){
this.tilesArray[target.tilePosition.y][target.tilePosition.x] = null;
target.destroy();
}, this);
break;
case 3:
this.tilesArray[this.playerPosition.y][this.playerPosition.x].tileValue = 1;
this.tilesArray[this.playerPosition.y][this.playerPosition.x].tint = 0xffffff;
break;
}
}
this.playerPosition.add(p.x, p.y);
var playerTween = game.add.tween(this.player).to({
x: this.playerPosition.x * gameOptions.tileSize + gameOptions.tileSize / 2,
y: this.playerPosition.y * gameOptions.tileSize + gameOptions.tileSize / 2
}, 100, Phaser.Easing.Linear.None, true);
playerTween.onComplete.add(function(){
if(this.playerPosition.y == gameOptions.fieldSize.rows || this.playerPosition.x == gameOptions.fieldSize.cols || this.tilesArray[this.playerPosition.y][this.playerPosition.x] == null || this.tilesArray[this.playerPosition.y][this.playerPosition.x].falling){
this.levelRestart();
}
else{
if(this.tilesArray[this.playerPosition.y][this.playerPosition.x].tileValue == 2){
if(this.isLevelComplete()){
if(levelNumber == 0){
levelNumber ++;
this.levelRestart();
}
else{
alert("ok you completed the game");
}
}
else{
var tween = game.add.tween(this.tilesArray[this.playerPosition.y][this.playerPosition.x]).to({
alpha: 0,
}, 100, Phaser.Easing.Linear.None, true);
this.levelRestart();
}
}
else{
game.input.onDown.add(this.beginSwipe, this);
}
}
}, this)
},
// function to check if the level is completed
isLevelComplete: function(){
for(var i = 0; i < gameOptions.fieldSize.rows; i++){
for(var j = 0; j < gameOptions.fieldSize.cols; j++){
if(this.tilesArray[i][j] != null && !this.tilesArray[i][j].falling && this.tilesArray[i][j].tileValue != 2){
return false;
}
}
}
return true;
},
// routine to start when the level is failed
levelRestart: function(){
var tween = game.add.tween(this.player).to({
alpha: 0,
width: gameOptions.tileSize / 4,
height: gameOptions.tileSize / 4
}, 500, Phaser.Easing.Linear.None, true);
tween.onComplete.add(function(){
game.state.start("TheGame");
}, this);
}
}
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.