Advertisement

Create a Whack-a-Mole Game in HTML5 With EaselJS

by

A few weeks ago, I showed you how to create a Whack-a-Mole (well, Whack-a-Worm) game using Flash and AS3. Now, following on from my introduction to EaselJS, we'll see how to use that library to create the same game with the HTML5 canvas and JavaScript.


Step 1: Brief Overview

Using pre made graphics we will code an entertaining Whack A Mole like game in HTML5 using the EaselJS library.

The player will be able to click the worms on the screen and get points.


Step 2: Interface

A simple and friendly interface will be used, this involves multiple shapes, buttons, bitmaps and more. The worm graphic used in this tutorial was downloaded from here under a Creative Commons License.

The interface graphic resources necessary for this tutorial can be found in the attached download.


Step 3: Get EaselJS

The EaselJS library will be used to build our game - make sure you read the Getting Started tutorial if you're new to this library.

You can download EaselJS from its official website.


Step 4: HTML Structure

Let's prepare our HTML document, it is a simple HTML structure to begin writing our app.

 
<!DOCTYPE html> 
<html> 
	<head> 
		<title>Whack A Worm</title> 
	</head> 
	<body> 
	</body> 
</html>

Step 5: Hide Mobile Hightlight

Let's add a little bit of CSS too, this line will remove the default highlight when you tap on an element using a mobile browser; without this the mobile experience would decrease drastically.

 
<!DOCTYPE html> 
<html> 
	<head> 
		<title>Whack A Worm</title> 
		 
		<style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> 
	 
	</head> 
	<body> 
	</body> 
</html>

Step 6: JavaScript Libraries

The following code adds the necessary JavaScript libraries for our app to work.

 
<!DOCTYPE html> 
<html> 
	<head> 
		<title>Whack A Worm</title> 
		 
		<style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> 
 
		<script src="easel.js"></script> 
		<script src="Tween.js"></script> 
		<script src="WhackAWorm.js"></script> 
	</head> 
	<body> 
	</body> 
</html>

Step 7: Call Main Function

In the next lines we call our constructor, this is the main function that will be created later in our JavaScript code.

 
<!DOCTYPE html> 
<html> 
	<head> 
		<title>Whack A Worm</title> 
		 
		<style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> 
 
		<script src="easel.js"></script> 
		<script src="Tween.js"></script> 
		<script src="WhackAWorm.js"></script> 
 
	</head> 
	<body onload="Main();"> 
	</body> 
</html>

Step 8: Canvas Tag

The Canvas is added in this line. We assign an ID to reference it later and also set its width and height.

 
<!DOCTYPE html> 
<html> 
	<head> 
		<title>Whack A Worm</title> 
		 
		<style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> 
 
		<script src="easel.js"></script> 
		<script src="Tween.js"></script> 
		<script src="WhackAWorm.js"></script> 
 
	</head> 
	<body onload="Main();"> 
		<canvas id="WhackAWorm" width="480" height="320"></canvas> 
	</body> 
</html>

Step 9: JavaScript

Let's begin our app creation!

Open your preferred JavaScript editor (any text editor will work, but you won't have syntax highlighting) and prepare to write your awesome app. Remember to save the file with a .js extension in your project folder.


Step 10: Define Canvas

We'll start by defining all the graphic and logic variables.

The next variables represent the HTML canvas element and the stage that will be linked to it. The stage variable will behave in a similar way to the AS3 stage.

 
/* Define Canvas */ 
 
var canvas; 
var stage;

Step 11: Background

This variable will store the title background image. (You can download the image above, or get it from the tutorial's source ZIP file.)

 
/* Background */ 
 
var titleBg;

Step 12: Title View

This is the Title View, which will be the first interactive screen to appear in our game. These variables store its components:

 
/* Title View */ 
 
var titleBgImg = new Image(); 
var titleBg; 
var playBtnImg = new Image(); 
var playBtn; 
var creditsBtnImg = new Image(); 
var creditsBtn; 
var titleView = new Container();

Step 13: Credits

This view will show the credits, year and copyright of the game, and these variables will be used to store it.

 
/* Credits */ 
 
var creditsViewImg = new Image(); 
var creditsView;

Step 14: Game View Background

The background for the Game View.

 
/* Game Bg */ 
 
var gameBgImg = new Image(); 
var gameBg;

Step 15: Alert

An alert will be shown when all the Worms have popped up, and will display the final score the player reached.

 
/* Alert */ 
 
var alertBgImg = new Image(); 
var alertBg;

Step 16: Score

The score value will be handled by the next variable.

 
/* Score */ 
 
var score;

Step 17: Worms

The following variables are used to store the worms' graphics and to refer to the last worm that was visible.

 
/* Worms */ 
 
var wormImg = new Image(); 
var worm; 
var lastWorm;

Step 18: Position Arrays

Arrays are used to store the worms final position. This is used to move the worm to the correct hole position when performing the pop-out animation.

 
var wormsX = [80, 198, 338, 70, 225, 376, 142, 356]; 
var wormsY = [11, 51, 34, 110, 136, 96, 211, 186];

Step 19: Additional Variables

These are the other variables we'll use; read the comments in the code to know more about them. (Some are self-explanatory.)

 
var centerX = 240; 
var centerY = 160; 
var gfxLoaded = 0; //used as a preloader 
 
var timerSource; 
var currentWorms = 0; //worms already shown 
var wormsHit = 0; 
var totalWorms = 10; //total of worms to display

Step 20: Main() Function

The Main() function will be the first to execute when the web page is loaded, because it is referred to in the onload attribute of the HTML document (see Step 7).

It calls the necessary functions to start the game. Check those functions in the next steps.

 
function Main() 
{ 
	//code... 
}

Step 21: Link Canvas

This code gets the HTML canvas ID and links it to the EaselJS Stage class. This will make the stage variable behave like the stage class in AS3.

 
/* Link Canvas */ 
	 
canvas = document.getElementById('WhackAWorm'); 
stage = new Stage(canvas);

Step 22: Enable Mouse Events

Mouse Events are disabled by default in EaselJS to improve performance; since we need those in the game we add the following line.

 
stage.mouseEventsEnabled = true;

Step 23: Load Graphics

This code is used to preload the graphics with the help of a function that we'll write later. It sets the Image object we created before to the source PNG file in our document folder. A name is given to detect which image is loaded and lastly the function that hadles the loaded images is called.

 
/* Load GFX */ 
 
titleBgImg.src = 'titleBg.png'; 
titleBgImg.name = 'titleBg'; 
titleBgImg.onload = loadGfx; 
 
gameBgImg.src = 'gameBg.png'; 
gameBgImg.name = 'gameBg'; 
gameBgImg.onload = loadGfx; 
 
playBtnImg.src = 'playBtn.png'; 
playBtnImg.name = 'playBtn'; 
playBtnImg.onload = loadGfx; 
 
creditsBtnImg.src = 'creditsBtn.png'; 
creditsBtnImg.name = 'creditsBtn'; 
creditsBtnImg.onload = loadGfx; 
 
creditsViewImg.src = 'creditsView.png'; 
creditsViewImg.name = 'credits'; 
creditsViewImg.onload = loadGfx; 
 
alertBgImg.src = 'alertBg.png'; 
alertBgImg.name = 'alertBg'; 
alertBgImg.onload = loadGfx; 
 
wormImg.src = 'worm.png'; 
wormImg.name = 'worm'; 
wormImg.onload = loadGfx;

Step 24: Set Ticker

The Ticker object provides a centralized tick or heartbeat, broadcast at a set interval through the tick() callback.
The following code sets the frame rate to 30 and deines the stage as the listener for the ticks.

The TweenJS class will listen to this tick to perform the animations.

 
/* Ticker */ 
 
Ticker.setFPS(30); 
Ticker.addListener(stage);

Step 25: Preload Function

Every time a graphic is loaded this function will run. It will assign each image to a bitmap object and check whether all the elements are loaded before proceeding. As you can see only five images are assigned to a bitmap but the gfxLoaded variable waits until seven items are loaded; this is so that it waits for the CreditsView and Worms graphic to be set in memory.

 
function loadGfx(e) 
{ 
	if(e.target.name = 'titleBg'){titleBg = new Bitmap(titleBgImg);} 
	if(e.target.name = 'gameBg'){gameBg = new Bitmap(gameBgImg);} 
	if(e.target.name = 'playBtn'){playBtn = new Bitmap(playBtnImg);} 
	if(e.target.name = 'creditsBtn'){creditsBtn = new Bitmap(creditsBtnImg);} 
	if(e.target.name = 'alertBg'){alertBg = new Bitmap(alertBgImg);} 
	/* --CreditsView 
	   --Worms */ 
	 
	gfxLoaded++; 
	 
	if(gfxLoaded == 7) 
	{ 
		addTitleView(); 
	} 
}

Step 26: Add Game View

When all the graphics are loaded the game background is added to the stage, it will be later covered by the Title View, this is to show something behind it when this view is tweened and removed.

 
function addTitleView() 
{	 
	/* Add GameView BG */ 
	 
	stage.addChild(gameBg);

Step 27: Title View

Now we place the TitleView in the stage and call a function that will add the mouse listeners to the buttons.

 
/* Title Screen */ 
 
playBtn.x = centerX - 25; 
playBtn.y = centerY + 35; 
 
creditsBtn.x = centerX - 40; 
creditsBtn.y = centerY + 80; 
			 
titleView.addChild(titleBg, playBtn, creditsBtn); 
 
stage.addChild(titleView); 
 
startButtonListeners('add'); 
 
stage.update(); 
}

Step 28: Start Button Listeners

This function adds the necesary listeners to the TitleView buttons.

 
function startButtonListeners(action) 
{ 
	if(action == 'add') 
	{ 
		titleView.getChildAt(1).onPress = showGameView; 
		titleView.getChildAt(2).onPress = showCredits; 
	} 
	else 
	{ 
		titleView.getChildAt(1).onPress = null; 
		titleView.getChildAt(2).onPress = null; 
	} 
}

Step 29: Show Credits

The Credits screen is shown when the user clicks the credits button, a mouse listener is added to the full image to remove it.

 
function showCredits() 
{ 
	playBtn.visible = false; 
	creditsBtn.visible = false; 
	creditsView = new Bitmap(creditsViewImg); 
	stage.addChild(creditsView); 
	creditsView.x = -203; 
	 
	Tween.get(creditsView).to({x:0}, 200).call(function(){creditsView.onPress = hideCredits;}); 
}

Step 30: Hide Credits

When the Credits screen is clicked it will be tweened back and removed from the stage.

 
function hideCredits() 
{ 
	playBtn.visible = true; 
	creditsBtn.visible = true; 
	Tween.get(creditsView).to({x:-203}, 200).call(function(){creditsView.onPress = null; stage.removeChild(creditsView); creditsView = null;}); 
}

Milestone

Let's stop here to make a quick test and make sure that our game code is working.

Take a look at the milestone here.

Keep in mind that some lines have been commented as some functions haven't been created yet.

Remember that the Milestones are included in the source files, so if for some reason your file doesn't mimic this one take a look at the source to see what could be causing that.


Step 31: Show Game View

The following lines remove the Title screen and leave the Game Screen visible. It also calls a function that will show the first worm.

 
function showGameView() 
{ 
	Tween.get(titleView).to({x: -480}, 200).call( 
		function(){ 
			startButtonListeners('rmv');  
			stage.removeChild(titleView);  
			titleView = null;  
			showWorm(); 
		} 
	); 
}

Step 32: Score Text

This code creates the Text object that will display the score.

 
score = new Text('0' + '/' + totalWorms, 'bold 15px Arial', '#EEE'); 
score.maxWidth = 1000;    //fix for Chrome 17 
score.x = 58; 
score.y = 21; 
stage.addChild(score);

Step 33: Check for Game Over

This code checks whether the Worms shown have passed the limit and calls an Alert if true.

 
function showWorm() 
{ 
	if(currentWorms == totalWorms) 
	{ 
		showAlert(); 
	}

Step 34: Remove Last Worm

This code checks whether a worm has been added and removes it if so.

 
else 
	{	 
		if(lastWorm != null) 
		{ 
			lastWorm.onPress = null; 
			stage.removeChild(lastWorm); 
			stage.update(); 
			lastWorm = null; 
		}

Step 35: Calculate Random Worm

The next line calculates a random number that will be used in the positions array to place a worm in a random hole.

 
var randomPos = Math.floor(Math.random() * 8);

Step 36: Add Worm

Now we create the worm and place it; a mouse listener is also added to handle the player clicks.

 
var worm = new Bitmap(wormImg); 
 
worm.x = wormsX[randomPos]; 
worm.y = wormsY[randomPos]; 
stage.addChild(worm); 
worm.onPress = wormHit; 
 
lastWorm = worm;

Step 37: Animation

A little animation will be displayed when the worm comes out: a small tween to its scaleY property. When the animation is finished the currentWorms variable increases and the showWorm() function is called again; this will create a loop that will end once the currentWorms variable reaches the value of totalWorms.

 
lastWorm.scaleY = 0.3; 
lastWorm.y += 42; 
stage.update(); 
 
Tween.get(lastWorm).to({scaleY: 1, y: wormsY[randomPos]}, 200).wait(1000).call(function(){currentWorms++; showWorm()});

Step 38: Hit Worm

This function handles a Worm's being clicked; it will basically raise the score and destroy the clicked worm.

 
function wormHit() 
{ 
	wormsHit++; 
	score.text = wormsHit + '/' + totalWorms; 
	 
	lastWorm.onPress = null; 
	stage.removeChild(lastWorm); 
	lastWorm = null; 
	stage.update(); 
}

Step 39: Show Alert

This function will stop the game and reveal the final score, showing and tweening the alert background.

 
function showAlert() 
{ 
	alertBg.x = centerX - 120; 
	alertBg.y = -80; 
	stage.addChild(alertBg); 
	 
	Tween.get(alertBg).to({y:centerY - 80}, 200).call(function() 
	{ 
		Ticker.removeAllListeners(); 
		var score = new Text(wormsHit + '/' + totalWorms, 'bold 20px Arial', '#EEE'); 
		score.maxWidth = 1000;    //fix for Chrome 17 
		score.x = 220; 
		score.y = 205; 
		stage.addChild(score); 
		stage.update(); 
	}); 
}

Step 40: Test

Save your work (if you haven't) and open the HTML file in the browser to see your HTML5 game working!


Conclusion

As you can see many of the game variables/parameters can be modified and adapted to your needs, so try creating your own version of the game!

I hope you liked this tutorial, thank you for reading!

Advertisement