HTML5 has exploded! Old news I know. Finally, it is possible to match the swish effects once reserved for Flash. Thus, my next project was to write a simple (very simple!) game using HTML5. On its own HTML5 is not a like-for-like replacement for Flash. It only becomes super-charged when mixed with a strong JavaScript library and some cool CSS.
The game covered in this post is a simple tile based memory game.
Players can simply click a tile to reveal the hidden image. Followed by a second selection to find the matching tile. If the tiles match they remain revealed. However, if they do not match they quickly flip back.
The code behind the scenes is simple JavaScript. I used the JQuery library which is included within the main document:
<article id="game"> <header> <div>Simple HTML5 Matching Game</div> </header> <section id="board"> </section> <a href='#' id="startGameButton">New Game</a> </article> Your browser does not support the audio element.
The above extract creates a header section, a region for the game and an audio tag. These elements are then styled using CSS which is included as follows:
During the initial load a small portion of JavaScript is executed. This instantiates a click handler, so that when a player clicks the ‘New Game’ hyper-link it runs the code that sets-up the game board. The code for setting up the click handler follows:
$(document).ready(function() { $('#startGameButton').click(function() { initTiles(); setTimeout("revealTiles(function() { onPeekStart(); })",iInterval); }); });
To start a game the player needs to hit the “New Game” hyper-link. This triggers the execution of JavaScript code which is included in the following script file:
Specifically the function called ‘initTiles’ followed by a call to the ‘revealTiles’ function:
function initTiles() { var iCounter = 0, curTile = null; initState(); // Randomly create twenty tiles and render to board for(iCounter = 0; iCounter < 20; iCounter++) { curTile = createTile(iCounter); $('#board').append(curTile.getHTML()); tiles.push(curTile); } }
The above function applies default values to various variables and creates twenty tile objects. Each object holds the necessary information to draw the tile in its alternate states during the game e.g. flipped or not flipped. Each tile object is fundamental to the game and the code for the tile is located in ’tile.js’. This file is included within the HTML. It contains the definition for a JavaScript object. The object is structured as follows:
function tile(id) { this.id = id; this.frontColor = '#fcfcfc'; this.backColor = '#fff'; this.startAt = 1000; this.flipped = false; this.backContentImage = null; this.flipCompleteCallbacks = new Array(); this.flip = function() { $("#" + this.id).flip({ direction: this.flipMethod, color: this.backColor, content: this.getBackContent(), onEnd: this.onFlipComplete() }); $("#" + this.id + " img").show(); this.flipped = true; }; this.onFlipComplete = function() { while(this.flipCompleteCallbacks.length > 0) { this.flipCompleteCallbacks[this.flipCompleteCallbacks.length - 1](); this.flipCompleteCallbacks.pop(); } }; this.revertFlip = function() { $("#" + this.id + " img").hide(); $("#" + this.id).revertFlip(); this.flipped = false; }; this.setBackContentImage = function(sBackContentImage) { this.backContentImage = sBackContentImage; }; this.setTileId = function(sIdOfTile) { this.id = sIdOfTile; }; this.setStartAt = function(iStartAt) { this.startAt = iStartAt; }; this.setFrontColor = function(sColor) { this.frontColor = sColor; }; this.setBackColor = function(sColor) { this.backColor = sColor; }; this.setFlipMethod = function(sFlipMethod) { this.flipMethod = sFlipMethod; }; this.getHTML = function() { return '<div id="' + this.id + '" class="tile ' + this.frontColor + '">' + '</div>'; }; this.getStartAt = function() { return this.startAt; }; this.getFlipped = function() { return this.flipped; }; this.getBackContent = function() { return '<img src="' + this.backContentImage + '" />'; }; this.getBackContentImage = function() { return this.backContentImage; }; this.addFlipCompleteCallback = function(callback) { this.flipCompleteCallbacks.push(callback); }; }
Skipping the lesson in JavaScript, the object contains a collection of methods which handles the flip and reverse flip action. It also holds several variables to store the state of the tile. As each tile is created within the initialisation function ‘initTile’, it is stored within the global array called ’tiles’. This is used later to draw the board.
Once the initialisation function is complete the game board in rendered to the page. This is managed by the ‘revealTiles’ function which is called as follows:
setTimeout("revealTiles(function() { onPeekStart(); })",iInterval);
The reveal function contains the following code:
function revealTiles(callback) { var iCounter = 0, bTileNotFlipped = false; for(iCounter = 0; iCounter tiles[iCounter].getStartAt()) { tiles[iCounter].flip(); } else { bTileNotFlipped = true; } } } iTimer = iTimer + iInterval; if(bTileNotFlipped === true) { setTimeout("revealTiles(" + callback + ")",iInterval); } else { callback(); } }
The reveal function allows the player to have a peak at the tiles hidden image. It is called via a timer e.g. every 300 milliseconds. This allows each tile to perform an initial flip at a given time. Therefore, the sequence in which the tiles flip is sequential, but, staggered. When all of the tiles are revealed a callback function ‘onPeekStart’ is executed after a 3 second wait – allowing the player to memorise the tiles – and then executes the function that reverses the flip, and therefore, hides the images again.
The code within ‘onPeekStart’ follows:
function onPeekStart() { setTimeout("hideTiles( function() { onPeekComplete(); })",iPeekTime); }
As you can see the code calls the ‘hideTiles’ function after waiting a defined number of milliseconds. Again this function makes use of a callback function. In this case the callback function is ‘onPeekComplete’. The ‘hideTiles’ function follows:
function hideTiles(callback) { var iCounter = 0; for(iCounter = 0; iCounter < tiles.length; iCounter++) { tiles[iCounter].revertFlip(); } callback(); }
The above function uses the global array ’tiles’ and calls the reverse action of each tile. This instructs the tile to perform the reverse flip animation. Once each tile has been instructed to flip the callback function is executed which we know to be the following:
function onPeekComplete() { $('div.tile').click(function() { iTileBeingFlippedId = this.id.substring("tile".length); if(tiles[iTileBeingFlippedId].getFlipped() === false) { tiles[iTileBeingFlippedId].addFlipCompleteCallback(function() { checkMatch(); }); tiles[iTileBeingFlippedId].flip(); } }); }
The above code binds the click event of each of the tiles to the in-line JavaScript function above. This contains the code which actions the click e.g. flip the tile to reveal the image. A third use of JavaScript callback pattern is used. This time the ‘checkMatch’ function is called when the flip action is complete. This contains the following:
function checkMatch() { if(iFlippedTile === null) { iFlippedTile = iTileBeingFlippedId; } else { if( tiles[iFlippedTile].getBackContentImage() !== tiles[iTileBeingFlippedId].getBackContentImage()) { setTimeout("tiles[" + iFlippedTile + "].revertFlip()", 2000); setTimeout("tiles[" + iTileBeingFlippedId + "].revertFlip()", 2000); playAudio("mp3/no.mp3"); } else { playAudio("mp3/applause.mp3"); } iFlippedTile = null; iTileBeingFlippedId = null; } }
This function is responsible for applying the rules of the game. When the first tile is flipped the function stores the id of the flipped tile within a global variable called ‘iFlippedTile ‘. When the second tile is flipped the two are compared. If they match the tiles remain image up and a favourable sound is played to celebrate the match. Alternatively, if the tiles do not match they are flipped. This action repeats until the player has matched all of the tiles.
sir..
where’s the code to change or which codes to chages if I want to add more than 10 images.
The source code can be found in my github account https://github.com/rheh/HTML5-canvas-projects/tree/master/matching_game
im too idiot to know, which file and codes line. i’ve inspect… and still dont know… I really am newbie… 😦
I tried running this game in windows xp, it does not load. any reasons why.
can you play sound effects once the cards are matched and for the
once that dont match, can you be prompted with a beep sound.
Sure, just a case of adding the sound call at the right point.
Hi, i updated the game, check out preview link:
https://rawgithub.com/asimkh/matching-game/master/index.html
Excellent – looks great. Glad to here my code has been used for something useful.
Can you give me your game script(code).
Hi. Please, how i add a sound when the card is flipped? Is it possible in canvas and html5? I want to add sound to one card and another sound to second card.thanks for your help
The cards are represented by the tile object. You could add a variable to it and set it using a setter e.g. tile.setFlipSound(‘flip.mp3’); Then when flipping a card add a call to the playAudio function e.g. playAudio(this.flipSound);
Can I make a match pair game using your this game? I want to make a game for matching similar but different objects rather than matching same objects.
Yes that is possible. Good luck.
Hi Geeksretreat,
Thanking you for providing such a nice game. Its really awesome.
I would like to use your code partially to re-create this game and use it in my game library for kids. I may use it for commercial purpose.
i am, therefore, seeking your permission for the same.
If you have any objection, please call it out so that i may look for some other source.
Thanking you in advance.
Your project sounds great. You may use the code for commercial purposes. Best of luck!
is there a way to use more than 10 images and randomly use them? i already managed to use another image, but than ther are mistakes in the game. eg one picture is used three times and an other just once.
It is possible, but, you’ll need to modify the getRandomImageForTile function to ensure the images are only used twice and chosen randomly.
Hi,
is it possible to add and define time for the games (with a timer) and a number of lives…
If it is possible, thank you for telling me how to make 😉
I’ve been thinking about that for one of my future post. In strikes me that the game state need wrapping around the current code. This would hold and keep track of lives, score, high-score, level and difficulty which would be factored into the main engine.
Hi Ray
This has got me close to what I’m looking for. I’m trying to create a game where one image is hidden by a grid of say 12 tiles. When one tile is clicked that part of the image is revealed. When another is clicked, the first is concealed again and the new tile is revealed (only one tile revealed at any one time). I can’t seem to find any code anywhere to help me with this. Do you know of any or are you able to advise on how your code could be manipulated to acheive this? Really appreciate any help you can offer.
Thanks
Marc
I want to reuse your script. I didnt see any license included in github so I am wondering what license do you choose foe your scripts like the html match card game script?
Feel free to use the code for any project. No license required. Good luck.
how to make this project to application for iphone ios?
i want to modify this and make it for iphone.thk you very much for this code
hello.i want to tell me if i can match two images with diffrent “name of image”. i am trying to find the code but i can’t…:-(
do you know how to display it offline.i saw tha i must have a file cache.manifest but i can’t understand how to do this
Unfortunately not, I’ve not tried the offline option before.
hello, I am trying to implement a timer and a click counter but i can’t seem to succeed. Can anyone help please? much obliged.
Hi Ray, thank you for posting the script. I would like to use your script partially or fully for commercial purpose. I saw you gave your approval for others on previous comments, and may I please have your permission directly? Thank you again!
Of course, you may use the code for any project
Very good script! I’m using it on a public touch display when no information is displayed.
I have only one problem: If somebody is clicking/taping very fast the flip function isn’t starting and you can’t see the picture after a match. How and where can I fix the problem? I’m not very good at Java and HTML…
If you are on a touch screen, you will have to used the touch event instead of the click event. Have a read of this http://www.html5rocks.com/en/mobile/touchandmouse/
can you give me a code that will work, many thanks xoxo
The code can be found here https://github.com/rheh/HTML5-canvas-projects/tree/master/matching_game
thanks for the link, I am thinking how to re-use such content, but i am having difficultly using it offline i am running windows xp. could there be an issue?
It should work on any O/S as it runs in a browser
I have implemented your code however it is not running when I hit the New Game link. Any ideas??
Hello @KristyI2211,
Could it be that you have forgotten to correct the Link to the JS files in the HTML code? I had a similar issue as yours while running from a file or from a local server until I realized that it tried to call JS from related folders.
Changing lines 8 and 9 to
http://../matching_game/js/tile.js
http://../matching_game/js/jquery.flip.js
Made it work for me.
@geeksretreat. It would be cool if you still included a license of any sort. It can be https://creativecommons.org/licenses/publicdomain/ (this seems to be what you mean).
paul
(grr, the comment function ate my code. You just need to change the absolute urls to src=”js/tile.js” and src=”js/jquery.flip.js” made it work; not even using a related directory).