Talking about CLOCKS - The Game game, Game development, HTML5, Javascript and Phaser.
Welcome to the first post of 2016. We’ll continue from the last 2015 tutorial about the creation of a HTML5 “CLOCKS – The Game” prototype using Phaser framework and ARCADE physics. In first step I showed you how to generate the first 10 levels, both with objects and with arrays generated by Tiled Map Eeditor. Now it’s time to add another feature to the game: randomly selecting the starting clock. Moreover, the starting clock has a different look, with another color and a visible clock face. From now on, I will also use levels generated by Tiled, but you are free to generate yours as you want. I had to turn some flat images into sprite sheet to store normal and highlighted clock status in a single file, and same thing goes for the hand. Highlighted clocks were made using a dark gray as I will tint them according to level tint color. When a level is generated, each clock I create is stored into an array, so selecting the starting clock is just picking a random element in the array. Then it’s just a matter of tinting some sprites and showing some other sprites. Have a look: Each three seconds a new level is generated, and a random clock is chosen as the starting clock. Here is the source code, still uncommented as it’s just in an embrional stage, but with next step you’ll be able to play the levels.
var game;
var gridSize = 40;
var levelWidth = 8;
var levelHeight = 8;
var level = 0;
window.onload = function() {
game = new Phaser.Game(640, 960, Phaser.AUTO, "");
game.state.add("Boot", boot);
game.state.add("Preload", preload);
game.state.add("PlayGame", playGame);
game.state.start("Boot");
}
var boot = function(game){};
boot.prototype = {
preload: function(){
this.game.load.image("loading","assets/sprites/loading.png");
},
create: function(){
game.scale.pageAlignHorizontally = true;
game.scale.pageAlignVertically = true;
game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
game.state.start("Preload");
}
}
var preload = function(game){};
preload.prototype = {
preload: function(){
game.load.spritesheet("smallclock", "assets/sprites/smallclock.png", 70, 70);
game.load.spritesheet("smallhand", "assets/sprites/smallhand.png", 70, 70);
game.load.spritesheet("bigclock", "assets/sprites/bigclock.png", 140, 140);
game.load.spritesheet("bighand", "assets/sprites/bighand.png", 140, 140);
game.load.image("smallclockface", "assets/sprites/smallclockface.png");
game.load.image("bigclockface", "assets/sprites/bigclockface.png");
},
create: function(){
game.state.start("PlayGame");
}
}
var playGame = function(game){};
playGame.prototype = {
create: function(){
this.clockGroup = game.add.group();
this.clockGroup.y = (game.height - gridSize * 16) / 2;
this.clocksArray = [];
game.stage.backgroundColor = 0x2babca;
for(var i = 0; i < levels[level].tiledOutput.length; i++){
switch(levels[level].tiledOutput[i]){
case 1:
this.clocksArray[i] = this.placeClock(new Phaser.Point(i % levelWidth * 2 + 1, Math.floor(i / levelHeight) * 2 + 1), "small");
break;
case 2:
this.clocksArray[i] = this.placeClock(new Phaser.Point(i % levelWidth * 2 + 2, Math.floor(i / levelHeight) * 2), "big");
break;
}
}
do{
var startClock = game.rnd.between(0, levels[level].tiledOutput.length - 1);
} while(levels[level].tiledOutput[startClock]==0);
this.clocksArray[startClock].children[0].frame = 1;
this.clocksArray[startClock].children[0].tint = 0x2babca;
this.clocksArray[startClock].children[1].frame = 1;
this.clocksArray[startClock].children[1].tint = 0xffffff;
this.clocksArray[startClock].children[2].visible = true;
game.time.events.add(Phaser.Timer.SECOND * 3, function(){
level = (level + 1) % 10;
game.state.start("PlayGame");
});
},
placeClock: function(clockObj, prefix){
var localClockGroup = game.add.group();
var clockSprite = game.add.sprite(clockObj.x * gridSize, clockObj.y * gridSize, prefix + "clock");
clockSprite.anchor.set(0.5);
localClockGroup.add(clockSprite);
var handSprite = game.add.sprite(clockObj.x * gridSize, clockObj.y * gridSize, prefix + "hand");
handSprite.anchor.set(0.5);
handSprite.tint = 0x2babca;
handSprite.angle = game.rnd.between(0, 359);
game.physics.enable(handSprite, Phaser.Physics.ARCADE);
handSprite.body.angularVelocity = game.rnd.between(levels[level].clockSpeed[0], levels[level].clockSpeed[1]) * (1 - 2 * game.rnd.between(0, 1));
localClockGroup.add(handSprite);
var faceSprite = game.add.sprite(clockObj.x * gridSize, clockObj.y * gridSize, prefix + "clockface");
faceSprite.anchor.set(0.5);
faceSprite.visible = false;
localClockGroup.add(faceSprite);
this.clockGroup.add(localClockGroup);
return localClockGroup;
}
}
var levels = [
// level 1
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
// level 2
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
// level 3
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
// level 4
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
// level 5
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
// level 6
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
// level 7
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
// level 8
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
// level 9
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]
},
// level 10
{
clockSpeed: [200, 450],
tiledOutput: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0]
}
]
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.