Matching game with Easel.js- Free time Series

Part of my journey in programming world is learning about game development. Initially i have tried several languages such as java and c++ but at the end I would like to with javascript. I have built one game before using js. The game is called Pong Ping which is the clone for the game Pong. This game was built purely using native javascript. You can find the demo and git resources below

DEMO

But today I would like to build a game base on a javascript game framework called Easel.js. The game that I am going to build is actually a very simple game where we flip to squares and if it is the same color it will disappear. The game will finish until every color is match. One example of the game in the video below, but they are using pictures.

Step 1

I will create the index.html file and make a reference to easel.js library. I choose to use cdn for this purpose. I will also need to make reference to main.js where all my javascript code wil be.

#index.html
<!DOCTYPE html>
<html>
<head>
<title>Pairing Game</title>
<script src="https://code.createjs.com/easeljs-0.8.2.min.js"></script>
<script src="js/main.js"></script>
</head>
<body onload="init()">
<canvas id="myCanvas" width="960" height="600"></canvas>
</body>
</html>

I need to make sure all the dom elements are fully loaded before the javascripts could be executed, so I am using the onload method to bind the javascript through the function init().

Step 2

I will then create the main.js file and setup easel.js environment.

#js/main.js
var squarHeight = 200;
var squareWidth = 200;
function init() {
var stage = new createjs.Stage("myCanvas");
var square = drawSquare();
stage.addChild(square);
stage.update();
}

Easel is using a Class called Stage as a container to display any element to the canvas defined. Now I would like to draw a square through the function drawSquare. I will utilise all the available APIs from easel.js

#js/main.js
function drawSquare() {
var graphics = new createjs.Graphics().setStrokeStyle(5).beginStroke("rgba(20,20,20,1)")
graphics.beginFill(randomColor()).rect(5,5,squareWidth,squareHeight);
var shape = new createjs.Shape(graphics);
return shape;
}
function randomColor() {
var num1 = Math.floor(Math.random()*255);
var num2 = Math.floor(Math.random()*255);
var num3 = Math.floor(Math.random()*255);
return "rgba("+num1+","+num2+","+num3+",1)";

}

First I will define the stroke size I would like to use, apply the stroke with a specific color, define the color of the square and create the square. The color of the square is a random color generated from the function randomColor. Below is how it will look like in the browser.

Step 3

After I have successfully rendered a square with a random color. I need to design how many rows and column for the square to fill in and also the algorithm to render one square in each columns and rows.

#js/main.js
##upated codes
var squarHeight = 200;
var squareWidth = 200;
var squareGap = 10;
var column = 3;
var row = 2;
function init() {
var stage = new createjs.Stage("myCanvas");
var square;
for(i=0; i < column*row; i++) {

square = drawSquare();
square.x = (squareWidth+squareGap)*(i%column);
square.y = (squarHeight+squareGap)*Math.floor(i/column);
stage.addChild(square);
stage.update();

}
}
function drawSquare() {
var graphics = new createjs.Graphics().setStrokeStyle(5).beginStroke("rgba(20,20,20,1)")
graphics.beginFill(randomColor()).rect(5,5,squarHeight,squareWidth);
var shape = new createjs.Shape(graphics);
return shape;
}
function randomColor() {
var num1 = Math.floor(Math.random()*255);
var num2 = Math.floor(Math.random()*255);
var num3 = Math.floor(Math.random()*255);
return "rgba("+num1+","+num2+","+num3+",1)";

}

From the above codes, I will get a rendered html something like below

There are many ways of implementing the square rendering. We could use looping in a multidimensional array or we can manipulate the the square size with some mathematical function. In this case, I use the later. However below is the algorithm if I would like to use the multidimensional method

#alternative
var positionX =0;
var positionY = 0;
for(i=0;i<row;i++) {
for(j=0;j<column;j++) {

square = drawSquare();
square.x = positionX;
square.y = positionY;
stage.addChild(square);
stage.update();
positionX += squareWidth+squareGap;
console.log(positionX);
}
positionX = 0;
positionY += squarHeight+squareGap;
}

Step 4

Again the objective of this game is to match a pair of colour together so I need modified the code in order for it to generate group of colours in pairs. To do that I will use an if else logic to make sure the two similar colour is use during the square rendering.

#js/main.js
var temp;
var genOnce = false;
function drawSquare() {
var color = randomColor();
var graphics = new createjs.Graphics().setStrokeStyle(5).beginStroke("rgba(20,20,20,1)")
 if(!genOnce) {
graphics.beginFill(color).rect(5,5,squarHeight,squareWidth);
temp = color;
genOnce = true;
}else {
graphics.beginFill(temp).rect(5,5,squarHeight,squareWidth);
genOnce = false;
}
 var shape = new createjs.Shape(graphics);
return shape;
}

This will render a group of squares something like this

Step 5

Next I would one to have each of the squares to be rendered in a random position so the pairs could be separated from each other. This can be achieve by first creating an array consist of all index of the squares then shuffle the array so the index number is randomly placed.

#js/main.js
var squarePlacement = [];
##function to generate array with all the squares index
function randomDoubleColor() {
for(i=0; i<totalTiles;i++) {
squarePlacement.push(i);
}

squarePlacement = shuffleArray(squarePlacement);

return squarePlacement;
}
##function of the array random shuffling
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}

Then a need to change the way of how I render the square. Instead of iterating through the length of total squares, I will iterate through the randomly shuffled array.

#js/main.js
function init() {

var stage = new createjs.Stage("myCanvas");
var square;
randomDoubleColor();
for(i=0; i < squarePlacement.length; i++) {


square = drawSquare();
square.x = (squareWidth+squareGap)*(squarePlacement[i]%column);
square.y = (squarHeight+squareGap)*Math.floor(squarePlacement[i]/column);
stage.addChild(square);
stage.update();

}
}

This will get me a group of squares like below

I can see the effect better if more squares is rendered

Step 6

My goals is now to create a function that could compare two squares which will be selected subsequently.

#js/main.js
var highlight = createjs.Graphics.getRGB(255, 0, 0);
var tileChecked;

I will start with defining a variable highlight which will be used to highlight the first selected squares and a variable tileChecked to store the same square.

#js/main.js
for(i=0; i < squarePlacement.length; i++) {


square = drawSquare();
square.x = (squareWidth+squareGap)*(squarePlacement[i]%column);
square.y = (squarHeight+squareGap)*Math.floor(squarePlacement[i]/column);
stage.addChild(square);
square.addEventListener("click", handleOnPress);
stage.update();

}
}

I will then create an event listener which will respond to a mouse click and trigger the function defined, handleOnPress. Now I will define the function as below

function handleOnPress(e) {

var tile = e.target;

if(!!tileChecked === false) {
tile.graphics.setStrokeStyle(5).beginStroke(highlight).rect(5, 5, squareWidth, squarHeight);
tileChecked = tile;
}else {
if(tileChecked.graphics._fill.style === tile.graphics._fill.style && tileChecked !== tile) {
tileChecked.visible = false;
tile.visible = false;
}else {
console.log("not match");
tileChecked.graphics.setStrokeStyle(5).beginStroke("rgba(20,20,20,1)").rect(5, 5, squareWidth, squarHeight);
}
tileChecked = null;
}

stage.update();
}

Basically the function will first check the variable tileChecked. If it is undefined, the selected square will be highlighted and the selected square object is save in the variable tileChecked. Otherwise(which I will expect to happen on the second click), the colour between the current selected square and the one which is stored in the variable tileChecked will be compared.

In this second comparison, if the colour is a match, I will make both the square disappear and if it is not I will remove the highlight and reset the variable tileChecked to undefined.

Step 7

To create a real puzzle game all of the colour should not be displayed. I will make the squares covered by grey squares and when it is click then it will reveal the colour. So when it is not a match, the grey square will cover the box again. To make it more playable, I will make sure other squares are not clickable during the comparison. I will also put some delay between when the second colour is display and when both squares disappear or turn to grey. Some modification need to be done in order for everything to work properly

function init() {

var stage = new createjs.Stage("myCanvas");

randomDoubleColor();
for(i=0; i < squarePlacement.length; i++) {

var color =randomColor();
console.log(color);
var square = drawSquare(color);
console.log(square);

square["color"] = square.graphics._fill.style;
square.graphics._fill.style = "rgb(140, 136, 136)";

square.x = (squareWidth+squareGap)*(squarePlacement[i]%column);
square.y = (squareHeight+squareGap)*Math.floor(squarePlacement[i]/column);
stage.addChild(square);
square.addEventListener("click", handleOnPress);
stage.update();

}

function handleOnPress(e) {

var tile = e.target;
tile.graphics.beginFill(tile.color).rect(5,5,squareHeight,squareWidth);
console.log(tile.mouseEnabled);
tile.mouseEnabled = false;
console.log(tile.mouseEnabled);
if(!!tileChecked === false) {

tileChecked = tile;
}else {
stage.mouseChildren = false;
tile.graphics.beginFill(tile.color).rect(5,5,squareHeight,squareWidth);
setTimeout(function() {
console.log("in");
console.log(tile);
console.log(tileChecked);

if(tileChecked.color === tile.color && tileChecked !== tile) {

tileChecked.visible = false;
tile.visible = false;



}else {
console.log("not match");
tile.graphics.beginFill("rgb(140, 136, 136)").rect(5,5,squareHeight,squareWidth);
tileChecked.graphics.beginFill("rgb(140, 136, 136)").rect(5,5,squareHeight,squareWidth);
}
tile.mouseEnabled = true;
tileChecked.mouseEnabled = true;
stage.mouseChildren = true;
tileChecked = null;
stage.update();

}, 1000);



}

stage.update();
}
}
function drawSquare(color) {



var graphics = new createjs.Graphics().setStrokeStyle(5).beginStroke("rgba(20,20,20,1)")
if(!genOnce) {
graphics.beginFill(color).rect(5,5,squareHeight,squareWidth);
temp = color;
genOnce = true;
}else {
graphics.beginFill(temp).rect(5,5,squareHeight,squareWidth);
genOnce = false;
}



var shape = new createjs.Shape(graphics);
return shape;
}

Below is a video of the game in action

This game can be enhanced furthermore by adding the winning or losing rules or maybe adding a timer to record each player finishing time. At the moment I will stop the development up until here. The full code could be found on GitHub below and anybody is free to use it for any other project.

DEMO

notes: There are probably many ways to implement this feature and and this is how I find the easiest way for me to implement this. Anybody is free to give a comment for any mistakes or improvement that I can apply. This guide is initially for my own self to learn and remember about what I have done, nonetheless anybody is welcome to follow this guide if you find it is very helpful.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.