logo
468x60-2-495


  • Home
  • Privacy Policy
  • About
search
Mar 27, 2012 Posted on Mar 27, 2012 in Hints and Tips | 10 comments

Quick Tip: A Simple Score Display for Flash Games

Almost all games out there use a scoring system to help players see their progress. It is essential to show the player’s score in a clear and fun way. In this Quick Tip we’re going to learn how to do just that!


Introduction

Click the button to add 20,000 points to your score:

In this Quick Tip we’re going to learn how to create a score display. To improve the quality of our display, we’re going to do two things:

  1. Add commas to our score, so it reads 1,600,000 instead of 1600000. This makes it easier for the player to figure out how big his or her score is.
  2. Make our score transition between values, instead of changing immediately. This gives the player a sense of achievement, because he or she actually sees his score grow.

In the end we’ll have a very simple and useful class, which you can easily use within any of your projects.

This class will only concern itself with displaying the score, not with calculating it.


Step 1: Creating Our Class

First off let’s create our class; I’ve named it ScoreDisplay:

package
{
	import flash.display.Sprite;

	public class ScoreDisplay extends Sprite
	{
		public function ScoreDisplay()
		{

		}
	}
}

Step 2: Adding Our Score Variables

Let’s slowly add some variables:

package
{
	import flash.display.Sprite;

	public class ScoreDisplay extends Sprite
	{
		//the score which is being shown, whilst it is increasing
		public var currentScore:uint;

		//the player's score
		private var score:uint;

		public function ScoreDisplay()
		{

		}
	}
}

We’re going to show our score in a TextField. If you’d like to use a Symbol when working with ScoreDisplay, you won’t need to create the text field by code. However, if you don’t want to use a Symbol, you’ll need to call createScoreField().

Do remember that if you want to use your own Symbol, you must give the text field inside that symbol the instance name of currentScoreField.

package
{
	import flash.display.Sprite;
	import flash.text.TextField;

	public class ScoreDisplay extends Sprite
	{
		//the text field which will show currentScore
		public var currentScoreField:TextField;

		//the score which is being shown, whilst it is increasing
		public var currentScore:uint;

		//the player's score
		private var score:uint;

		public function ScoreDisplay()
		{

		}

		//if the developer won't link this class to a symbol, this method must be called
		public function createScoreField():void
		{
			currentScoreField = new TextField();
			addChild(currentScoreField);
		}
	}
}

Step 3: Changing and Setting Our Score

Now let’s start thinking what we’d like to do with our ScoreDisplay class. We’d like to be able to set a score, as well as add or subtract from the player’s score. So let’s create those methods!

package
{
	import flash.display.Sprite;
	import flash.text.TextField;

	public class ScoreDisplay extends Sprite
	{
		//the text field which will show currentScore
		public var currentScoreField:TextField;

		//the player's score
		private var score:uint;

		//the score which is being shown, whilst it is increasing
		private var currentScore:uint;

		public function ScoreDisplay()
		{

		}

		//if the developer won't link this class to a symbol, this method must be called
		public function createScoreField():void
		{
			currentScoreField = new TextField();
			addChild(currentScoreField);
		}

		public function setScore(_value:uint):void
		{
			score = _value;
		}

		public function changeScore(_change:uint):void
		{
			score += _change;
		}
	}
}

Step 4: Displaying Our Score

So far so good, we can now set and change the score’s value. But how will we display this? Even though it might not yet seem very useful, we’ll be using an enter frame event listener. Don’t worry it will make sense!

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;

	public class ScoreDisplay extends Sprite
	{
		//the text field which will show currentScore
		public var currentScoreField:TextField;

		//the player's score
		private var score:uint;

		//the score which is being shown, whilst it is increasing
		private var currentScore:uint;

		public function ScoreDisplay()
		{
			addEventListener(Event.ENTER_FRAME, showScore, false, 0, true);
		}

		//if the developer won't link this class to a symbol, this method must be called
		public function createScoreField():void
		{
			currentScoreField = new TextField();
			addChild(currentScoreField);
		}

		public function setScore(_value:uint):void
		{
			score = _value;
		}

		public function changeScore(_change:uint):void
		{
			score += _change;
		}

		private function showScore(event:Event):void
		{
			currentScoreField.text = String(score);
		}
	}
}

Step 5: Our Partly Finished Class

If we’d like to use our class in a project, it would look like this. Seems to work right – the score changes – but we aren’t done. Remember what we wanted to do?

  1. Add commas to our score, so it reads 1,600,000 instead of 1600000.
  2. Make our score transition between values, instead of changing immediately.

Step 6: Adding Commas

Let’s start with the first goal, adding commas.

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;

	public class ScoreDisplay extends Sprite
	{
		//the text field which will show currentScore
		public var currentScoreField:TextField;

		//the player's score
		private var score:uint;

		//the score which is being shown, whilst it is increasing
		private var currentScore:uint;

		public function ScoreDisplay()
		{
			addEventListener(Event.ENTER_FRAME, showScore, false, 0, true);
		}

		//if the developer won't link this class to a symbol, this method must be called
		public function createScoreField():void
		{
			currentScoreField = new TextField();
			addChild(currentScoreField);
		}

		public function setScore(_value:uint):void
		{
			score = _value;
		}

		public function changeScore(_change:uint):void
		{
			score += _change;
		}

		private function showScore(event:Event):void
		{
			currentScoreField.text = addCommas(score);
		}

		private function addCommas(_score:uint):String
		{
			//a string, which will have the score with commas
			var scoreString:String = new String();

			//the amount of characters our score (without commas) has
			var scoreLength:uint = _score.toString().length;
			scoreString = "";

			//add the commas to the string
			for (var i:uint=0; i<scoreLength; i++) {
				if ((scoreLength-i)%3 == 0 && i != 0) {
					scoreString += ",";
				}
				scoreString += _score.toString().charAt(i);
			}

			return scoreString;
		}
	}
}

Step 7: Transitioning Between Scores

Now let’s work on our second goal; transitioning between score values, instead of changing to the new value immediately.

For this we can use the awesome capabilities of the Tween class. Most times we think of the Tween class for moving display objects, but you can use it to change any numerical value, including our score.

package
{
	import fl.transitions.Tween;
	import fl.transitions.easing.*;

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;

	public class ScoreDisplay extends Sprite
	{
		//the amount of time (in ms) which is needed to transition from one score value to another one
		private static const TRANSITION_LENGTH:uint = 500;

		//the score which is being shown, whilst it is increasing
		public var currentScore:uint;

		//the player's score
		private var score:uint;

		//the text field which will show currentScore
		private var currentScoreField:TextField;

		//this will tween the current score's value
		private var currentScoreTween:Tween;

		public function ScoreDisplay()
		{
			addEventListener(Event.ENTER_FRAME, showScore, false, 0, true);
		}

		//if the developer won't link this class to a symbol, this method must be called
		public function createScoreField():void
		{
			currentScoreField = new TextField();
			addChild(currentScoreField);
		}

		public function setScore(_value:uint):void
		{
			score = _value;	

			tweenCurrentScore();
		}

		public function changeScore(_change:uint):void
		{
			score += _change;

			tweenCurrentScore();
		}

		private function showScore(event:Event):void
		{
			currentScoreField.text = addCommas(currentScore);
		}

		private function tweenCurrentScore():void
		{
			currentScoreTween = new Tween(this, "currentScore", None.easeNone, currentScore, TRANSITION_LENGTH, true);
		}

		private function addCommas(_score:uint):String
		{
			//a string, which will have the score with commas
			var scoreString:String = new String();

			//the amount of characters our score (without commas) has
			var scoreLength:uint = _score.toString().length;
			scoreString = "";

			//add the commas to the string
			for (var i:uint=0; i<scoreLength; i++) {
				if ((scoreLength-i)%3 == 0 && i != 0) {
					scoreString += ",";
				}
				scoreString += _score.toString().charAt(i);
			}

			return scoreString;
		}
	}
}

We’re Done!

And that’s it! You could extends this class and maybe add some sounds or “fancy graphics”. I hope you had a great time and learnt something, cheers!



View full post on Activetuts+

Feb 18, 2012 Posted on Feb 18, 2012 in Hints and Tips | 10 comments

Simple Harmonic Motion and Its Applications in Games – Tuts+ Premium

Premium members: here’s this week’s tutorial. Simple harmonic motion is a type of movement commonly used to describe pendulums and springs. In this tutorial, you’ll learn the concepts behind this type of motion, and understand the many different ways you can apply this in your games: from an animated health warning, to the motion of attacking enemy ships.


Premium Preview

This tutorial focuses mainly on the mathematical formulae behind simple harmonic motion, and on implementing them in ActionScript, and uses a number of different examples to demonstrate how this could be used in games rather than ending up with one main example.

With that said, here’s one of the demos. Click to activate the pendulum, then try to move the green circle through using the arrow keys, without getting hit.


Read the Full Tutorial

Premium members can access the full tutorial right away!

If you’re not yet a Premium member, you can still read the first few steps of the tutorial, which are enough to introduce the main equation and use it to create an oscillating particle..


Tuts+ Premium Membership

We run a Premium membership system which periodically gives members access to extra tutorials, like this one! You’ll also get access to Psd Premium, Vector Premium, Audio Premium, Net Premium, Ae Premium, Cg Premium, Photo Premium, and the new Mobile Premium too. If you’re a Premium member, you can log in and download the tutorial. If you’re not a member, you can of course join today!

Also, don’t forget to follow @envatoactive on twitter, circle us on Google+, like us on Facebook, and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.



View full post on Activetuts+

Nov 4, 2011 Posted on Nov 4, 2011 in Hints and Tips | 10 comments

Quick Tip: Create a Simple Points System Using AS3

In this Quick Tip you will learn how to make a simple points system that can be extended into your own games. This tutorial is for total beginners, and in it you’ll learn how to create a set of buttons that the player can click to add or subtract points to or from their score. Simple!

Although this tutorial is for beginners to Flash programming, you will need to know a little bit about using the drawing tools in Flash Professional. If you need to learn how to use the drawing tools, read this article.


Final Result Preview

Let’s take a look at the final result we will be working towards:


Step 1: Setting Up Your Flash File

Open up Flash and create a new Flash Document. Set the Document Size to 550x400px, the FPS (Frames per Second) to 24 and set the document class to Main.

This is how it should look.

Step 2: Creating the Graphics

These are the graphics you will need to create.
These are the graphics you will need to create.

To create the graphics, use the Oval Tool to create four circles with a #000000 (Black) outline and a stroke size of 12.50.

Each circle should have a different fill color. The fill colours are as follows:

  • 10 Coin: #993300
  • 50 Coin: #999999
  • 100 Coin: #FFCC00
  • -30 Coin: #990000

After creating the coins, use static textboxes to write their respective values as given in the image above. The font I will be using throughout this tutorial is Futura LT Heavy, with a size of 50, but feel free to use your own font and font size. After completing the instruction you should have a 10 Coin, 50 Coin, 100 Coin, and a -30 Coin.

We will now convert each coin into a MovieClip. Select the 10 Coin and press F8. You should see a dialog like this:

The image has everything filled out. Make sure you write down the same things in your dialog.
The image has everything filled out. Make sure you write down the same things in your dialog.

Repeat this step for the 50 Coin, 100 Coin and the -30 Coin and input the following under the Name and Class boxes for each Coin:

  • 50 Coin: FiftyCoin
  • 100 Coin: HundredCoin
  • -30 Coin: BadCoin

Once you have created MovieClips out of all the Coins, select them all and delete them off the stage. We will be adding them back again later on, using code.

To finish off this step create a static textbox with the text “SCORE:” and position it with an X value of 135 and a Y value of 327.


Step 3: Setting Up the Package and Main Class

In this step we will set up our package and the Main Class.

Create a new ActionScript Class and under Class Name type Main. Once you have created the class, save it in the same folder as your Flash file, and make sure it is saved as Main.as.

Make sure your dialog looks like this.
Make sure your dialog looks like this.

Enter the code below into your Main.as file, then save it.

package {
	//imports the necessary classes
	import flash.display.MovieClip
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFieldType;
	import flash.events.Event;

	public class Main extends MovieClip {
        var tenCoin:TenCoin = new TenCoin(); //Creates a new instance of the Ten Coin
		var fiftyCoin:FiftyCoin = new FiftyCoin(); //Creates a new instance of the Fifty Coin
		var hundredCoin:HundredCoin = new HundredCoin(); //Creates a new instance of the Hundred Coin
		var badCoin:BadCoin = new BadCoin(); //Creates a new instance of the -30 Coin

		var score:Number = 0; //Sets the score to zero
		var scoreText:TextField = new TextField(); //Creates a textfield to display the score
		var scoreTextFormat:TextFormat = new TextFormat("Futura LT Heavy", 50, 0x000000); //Creates a new format for Score textfield, replace "Futura LT Heavy" with the font that you are using 

		public function Main() {
			displayObjects(); //The function that we will use to display all of the graphic on the stage
			setUpEventListeners(); //The function that we will use to add our Event Listeners
		}

First we import the classes that we need and then we set up our document class. We then extend the Main Class from MovieClip; we could use Sprite, but it doesn’t really matter. After that, we declare the variables that we are using and we add code to our Main() function (our “constructor function”).

The Main() function will display all of the coins we created on the stage and it will also add the Event Listeners that we need to use.

Note: You’ll need to embed the font into your FLA in order to make it display in dynamic text fields if your user doesn’t have the font installed. I haven’t done this here, to keep things simple.


Step 4: Coding the displayObjects() Function

The displayObjects() Function is called from the Main() function. The purpose of this function is to add the coins and the score textbox to the stage and to position them at their proper location.

function displayObjects() {
	// Sets the position of the Ten Coin
	tenCoin.x = 72;
	tenCoin.y = 200;
	// Sets the position of the Fifty Coin
	fiftyCoin.x = 207;
	fiftyCoin.y = 200;
	// Sets the position of the Hundred Coin
	hundredCoin.x = 342;
	hundredCoin.y = 200;
	// Sets the position of the -Thirty Coin
	badCoin.x = 477;
	badCoin.y = 200;
	//Positions the score textbox and sets its type to dynamic so that it can be changed through code
	scoreText.type = TextFieldType.DYNAMIC;
	scoreText.x = 305;
        scoreText.y = 327;
	scoreText.width = 300;
	//Sets the format of the score textbox
        scoreText.defaultTextFormat = scoreTextFormat;
	//Adds everything to the stage
	addChild(tenCoin);
	addChild(fiftyCoin);
	addChild(hundredCoin);
	addChild(badCoin);
	addChild(scoreText);
}

Step 4: Coding the setUpEventListeners() Function and the Event Handlers

Now that we have added objects to the stage we have to create event handler functions that are triggered when clicking on the coins. We will also need an updateScore() function to use so that the score gets updated and doesn’t stay the same.

function setUpEventListeners() {
	//Changes all of our MovieClips into Buttons
	tenCoin.buttonMode = true;
	fiftyCoin.buttonMode = true;
	hundredCoin.buttonMode = true;
	badCoin.buttonMode = true;
	//Adds the event listeners to add points to the score
	tenCoin.addEventListener(MouseEvent.CLICK, addTenPoints);
	fiftyCoin.addEventListener(MouseEvent.CLICK, addFiftyPoints);
	hundredCoin.addEventListener(MouseEvent.CLICK, addHundredPoints);
	badCoin.addEventListener(MouseEvent.CLICK, removeThirtyPoints);
	//Adds the update function to update the score
	stage.addEventListener(Event.ENTER_FRAME, updateScore);
}

Now we must code the functions that change and update the score.

function addTenPoints(evt:MouseEvent){
	score += 10; //Adds 10 points to the score
}

function addFiftyPoints(evt:MouseEvent){
	score += 50; //Adds 50 points to the score
}

function addHundredPoints(evt:MouseEvent){
	score += 100; //Adds 100 points to the score
}

function removeThirtyPoints(evt:MouseEvent){
	score -= 30; //Subtracts 30 points from the score
	// This if statement doesn't allow the score to go below zero
	if(score < 10) {
		score -= score;
	}
}

function updateScore(evt:Event){
	scoreText.text = String(score); //This converts the score variable from a number to a string, because our score textbox can only display strings
}
} //Closes the class
} //Closes the package

Your code is now ready for testing. Press CTRL+Enter (CMD+Enter on a Mac) and watch your points system come to life!


Review

Now you might be thinking, “I’ve wasted my time, all this tutorial taught me to do was to create some buttons that give you points when you click them” – but you have learned more than this.

Look at this as a foundation for a more advanced points system. You learned how to use += and -= to add or subtract from a number, you learned how to use event listeners, you learned how to create a function to update objects while the SWF is running, and you learned how to change a Number to a String and display it in a dynamic textbox that you created entirely through code!


Conclusion

This points system can easily be extended into your own games. For those of you who are more experienced at Flash, try creating a game that uses a hitTestObject function and adds points when you hit an object.

I hope you learned something new today. Thanks for reading!



View full post on Activetuts+

Sep 17, 2011 Posted on Sep 17, 2011 in Hints and Tips | 10 comments

Learn HTML5 With This Simple Avoider Game Tutorial

In this tutorial (the first of a series), you’ll learn the basics of HTML5 game development with JavaScript and the <canvas> element. You don’t need to have any programming experience, or even any HTML experience (apart from this one article). Let’s get started!


Introduction

It would be difficult to have missed the “HTML5 vs Flash” articles that have sprung up all over the web, particularly since Steve Jobs’s Thoughts on Flash last year, and Microsoft’s announcement this week that Windows 8′s web browser won’t support Flash on tablets by default. I’m not going to get into that debate here; whatever your opinion, there’s no harm in learning HTML5. Even if you know Flash, it doesn’t hurt to have another tool in your kit.

This tutorial does not require you know know Flash, or to have had any experience of programming before. In fact, everything that you need to know before you get started is explained in this single article: Get Up to Speed With HTML. That’s it! If you can follow that, you can follow this.

I’m basing this series on my Flash tutorial series, which in turn was based on an even older Flash tutorial by a guy named FrozenHaddock (to whom I am very grateful for letting me use his ideas). This isn’t a direct port of either tutorial, however; I’ll be completely rewriting the code and the explanations to suit HTML5.

A couple of notes:

  • Cross-browser compatibility is a real and important issue in web development, but we’re going to be a little selfish and focus on making sure our game works in exactly one browser: Chrome. Rest assured, we will deal with other browsers (including mobile) in other Activetuts+ tutorials, but for the time being, we’ll stick with Chrome, so that we don’t have to split our focus.
  • Clean code is more important in HTML5 than in a lot of other platforms, because the underlying programming language (JavaScript) will let you get away with a lot. So, we’re going to make sure that you get in the habit of writing decent code… eventually. We’ll be a little messy at the start, just to get things rolling and avoid making you scroll through thousands of words on “best practices” before actually getting to do anything.

In this first part of the tutorial, we’ll just be setting everything up and putting in some very basic game mechanics. Future parts will add multiple spawning enemies, high scores, menu screens, multiple levels, and all that stuff.

Enough talk – let’s get started!


Setting Up

First thing to do is create a .html file. You can use a basic text editor for this, or spend a few hundred dollars on software specifically designed for HTML development; personally, I’d stick with free software for now. Here are three recommendations: TextEdit (for Mac), Notepad++ (for Windows), and Sublime Text 2 (for Windows, OS X, and Linux). Take your pick.

Create a new file, and enter the following:

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
	</head>
	<body>

	</body>
</html>

If you don’t understand what any of that does, read my basic guide to HTML.

Create a new folder on your hard drive called AvoiderGame, and save this HTML file inside it as game.html. If you load it right now, it’ll just show a blank white page (as you know), so put a paragraph of text in there just to make sure everything’s okay. I’ll add a link to this tutorial, but you could enter anything you like – your name and website, perhaps?

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
	</head>
	<body>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

JavaScript

Okay, now, you will not be surprised to hear that we will soon be writing some JavaScript – remember, JavaScript lets web pages do things, and that’s exactly what we need for making games. We’ll put all our JavaScript in an external file, in order to keep things tidy, and put this file in a separate folder, to keep things tidier still.

So, create a new folder, called js inside your AvoiderGame folder. Then, create a new, empty text file, and save it as main.js inside this new AvoiderGame/js/ folder.

Alter your HTML to refer to this JS file:

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
	</head>
	<body>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

Note that I haven’t written src="http://active.tutsplus.com/...whatever.../js/main.js", or src="C:\AvoiderGame\js\main.js"; this way, we’re telling the HTML page, “look for a js folder in the same directory as you, and then use the main.js file that’s inside it.” It’s called a relative path.

If you want to test that this is working, put alert("Working!"); in your JS file, then load the HTML page. If you get a dialog box, everything’s okay.

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
	</head>
	<body>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

CSS

While we’re at it, let’s link an external CSS file as well; we can use it to make the text look nicer, and we might need to use CSS in the game later.

Create a new folder inside AvoiderGame called css, and then create a new, empty text file called style.css inside that. Modify your HTML like so:

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

I’m going to modify my CSS file to match some styles we often use on demo pages here at Activetuts+; feel free to copy it, come up with your own, or leave yours blank:

body {
	background: #ffffff;
	text-align: center;
	padding: 20px;
	color: #575757;
	font: 14px/21px Arial,Helvetica,sans-serif;
}

a {
	color: #B93F14;
}

a:hover {
	text-decoration: none;
}

ol {
	width: 600px;
	text-align: left;
	margin: 15px auto
}

This tutorial isn’t about CSS, so if you don’t understand that, don’t worry about it. (If you’re curious, you can look up the meaning of those CSS attributes on W3Schools.com.)

Okay, that’s the dull setup out of the way. You can see how the page looks by clicking here, and you can download the entire source so far in a ZIP file here. Let’s create our avatar!


Get Your Head in the Game

We need an image that will represent our player’s character in this game. Use whatever you like – a photograph of your face, your Twitter avatar, a picture you’ve drawn – but make sure it has a transparent background, that it’s roughly circular, and that it’s about 30x30px.

The original tutorial on which this one is based used a skull. I’m not sure why, but I suspect it was an attempt to subvert games’ typical anti-skeleton stance; after all, under our skin, doesn’t every one of us have a skull?

I’m not one to break with tradition, so I’ll use a skull here too. You can download mine by right-clicking it, if you don’t want to make your own:

Learn HTML5 With This Simple Avoider Game Tutorial

And before you ask: yes, I am available for commission.

Whatever you choose, save it as avatar.png inside a new folder, called img inside AvoiderGame. Your folder structure now looks like this:

/AvoiderGame/
	game.html
	/css/
		style.css
	/js/
		main.js
	/img/
		avatar.png

So how do we get this into our game? If you’ve been paying attention, you’ll probably suggest this:

<img src="img/avatar.png" alt="Avatar" />

And, it’s true, that would put the avatar in our page! But it’s not what we’re going to use.

Canvas

An img element shows a single image, loaded from a PNG or JPG (or whatever) file. The canvas tag, new to HTML5, can generate an image dynamically, made up of other, smaller images, text, primitive shapes, and so much more, if you desire. Its contents can be modified at any point, so you can give the illusion of motion – or of interaction, if you make the contents change according to what the user does.

We create a canvas in the same way that we create any other HTML element:

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<canvas></canvas>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

…though, if you look at this, you won’t be able to see anything there. It’s invisible, so the only effect it has is to move the text down a little.

With CSS, we can give it an outline so that we can tell it apart from the background. Add this to your CSS:

canvas {
	border: 1px solid black;
}

Check it out. It’s kinda small, though; let’s make it 400px by 300px (old-school TV dimensions):

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<canvas width="400" height="300"></canvas>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

That’s better. Now, I said we could add images to the canvas dynamically, so let’s do that next.

Functions

Remember in the HTML guide I showed you how to make things happen when you clicked HTML elements? Here’s a quick recap:

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<canvas onclick="alert('Clicked the canvas');" width="400" height="300"></canvas>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

If you click the canvas, you’ll get a dialog box message. This is because alert() is a JavaScript function: it’s a shortcut to a few lines of code. We can write our own functions in our JS file. Open main.js and enter the following:

function alertSeveralTimes() {
	alert("Hello!");
	alert("Look, we can run several messages in a row.");
	alert("Annoyed yet?");
}

(Delete the original alert("Working!"); if you haven’t already.)

Do you see how this works? We have created a new function called alertSeveralTimes(), whose contents are inside the curly braces ({ and }). When we tell the browser to run this alertSeveralTimes() function, it will run each of the alerts in turn, one after the other.

Let’s try it out:

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<canvas onclick="alertSeveralTimes();" width="400" height="300"></canvas>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

Try it! We’ve effectively bundled up several alert() functions into one bigger function called alertSeveralTimes(), and told it to run whenever the canvas is clicked.

You might be wondering why the alert("Working!") ran as soon as we opened the page, but the alertSeveralTimes() didn’t, even though they were both in the same place (at the top of main.js). It’s because of that magic keyword function; when the browser sees this, it doesn’t think, “aha, this is some code I must run immediately!”, it thinks, “aha, this is some code I must bundle up into a new function, which I can run later!”

Anyway. Now let’s make our function do something to the canvas. Making it load an image is a little tricky, so we’ll start with something a bit simpler: changing its size.

Modifying the Canvas

One of the most amazing features of JavaScript is its ability to change the HTML of the page. Check this out; modify your JS file so that it contains this:

function changeCanvasSize() {
	gameCanvas.width = 600;
	gameCanvas.height = 800;
}

You can probably guess what this is doing: it takes the canvas element, and modifies its width and height attributes (we don’t need to use quotes around numbers in JavaScript, unlike in HTML attributes).

Except… how does it know that gameCanvas refers to the canvas that we have in our page?

Well, it doesn’t… yet. We have to make it realise that.

First, we have to give the canvas element an id (short for “identification”) attribute; this is just a name that we use so that we can refer to it in JavaScript later:

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<canvas id="gameCanvas" onclick="alertSeveralTimes();" width="400" height="300"></canvas>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

While we’re at it, let’s make the onclick attribute point to our new changeCanvasSize() function:

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<canvas id="gameCanvas" onclick="changeCanvasSize();" width="400" height="300"></canvas>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

This still isn’t quite enough. We have to let the JavaScript know that it’s dealing with an element from the HTML page (or ‘HTML document’, as it’s more correctly known):

function changeCanvasSize() {
	document.getElementById("gameCanvas").width = 600;
	document.getElementById("gameCanvas").height = 800;
}

Now, I know, this doesn’t seem entirely logical. Why is gameCanvas suddenly in quotes? Why do we use document.getElementById("gameCanvas") instead of just, say, getDocumentElement("gameCanvas"), or even document.gameCanvas? I promise, this will all become clear during the tutorial series, but for now, just go with it, please.

Test out your new code. The canvas resizes itself as soon as you click on it. Awesome!

Now, I should warn you: programmers are lazy. We hate writing the same code over and over again, and if there’s any way we can reduce the typing required, we’ll take it. So, let me introduce you to a nice shorthand way of referring to the canvas:

function changeCanvasSize() {
	var gameCanvas = document.getElementById("gameCanvas");
	gameCanvas.width = 600;
	gameCanvas.height = 800;
}

See how that works? Just as the function keyword says, “hey, wrap all this code up under the name changeCanvasSize(), please”, the var keyword says, “hey, use the word gameCanvas to refer to the HTML element with an ID of “gameCanvas”, please”. Then (in lines 3 and 4, above), we can use this new shorthand gameCanvas in please of the longer document.getElementById("gameCanvas") – because they refer to the same thing.

That’s important: we haven’t created a new canvas; we’ve just made gameCanvas refer to the existing canvas element.

However, it is possible to use var to create something new…

Click to Skull

Like I said, we’re moving towards adding an image to the (currently empty) canvas. But before we can do that, we have to load the image. And before we can do that, we have to have something to load the image into.

Modify your JS like so:

function changeCanvasSize() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	gameCanvas.width = 600;
	gameCanvas.height = 800;
}

(I’ve added a blank line to clearly separate the var statements from the rest.)

Here, we’re using the var keyword again – but this time, it says something subtly different: “hey, create a new Image object and use the word avatarImage to refer to it from now on, please.” The Image object is basically like a img element; the crucial difference here is, it’s not in the HTML. We’ve created this brand new element, but it’s nowhere in the HTML; it’s just floating around in the JavaScript aether. I find that a bit weird.

Just like an img element in the page, this Image is pretty much useless without setting its src, so do that next:

function changeCanvasSize() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	gameCanvas.width = 600;
	gameCanvas.height = 800;

	avatarImage.src = "img/avatar.png";
}

(Once again I’m using a blank line to keep bits of code that do different things separated from each other (like paragraphs in text), and once again I’m using a relative path to refer to a file’s location.)

So this is now loading the image, but you’ll have to take my word for it at the moment, since it’s still out there in the aether where we can’t see it. However, we can check its other attributes:

function changeCanvasSize() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	gameCanvas.width = 600;
	gameCanvas.height = 800;

	avatarImage.src = "img/avatar.png";
	alert(avatarImage.width);
}

We’re telling it to show us a dialog box containing the value of the width attribute of our image. Check it on your code and see what you get; I get 29, which is exactly right.

With just one more line of code, we can draw the avatar on the canvas:

function changeCanvasSize() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	gameCanvas.width = 600;
	gameCanvas.height = 800;

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, 0, 0);
}

Let’s break this down:

  • gameCanvas.getContext("2d"): We don’t actually draw directly on the canvas, we draw onto what’s called a “drawing context”; this lets us determine whether we want to draw in 2D or 3D. Okay, there’s no 3D context at the moment, but this is letting us plan for the future.
  • drawImage(): Pretty straightforward. This is a function that lets us draw an image onto the context of a canvas.
  • avatarImage: This is the image object we’ve got floating around in the aether, remember?
  • 0, 0: These are the coordinates at which we want to draw the image. In school, you’re taught that (0, 0) is the bottom-left of the page; on a computer, it’s the top-left (the x-axis points to the right, and the y-axis points downwards).

Take a look. It works! (If it doesn’t, remember that you should be viewing this in Chrome; I don’t guarantee that this will work in any other browser.)

Multiple Skulls

The drawImage() function works like a potato stamp:

Learn HTML5 With This Simple Avoider Game Tutorial
Photo by jimmiehomeschoolmom

It just takes the contents of the image object and clones them onto the canvas; of course, we’re dealing with pixels, not paint, but you get the idea.

This means we can add multiple skulls to the canvas, like so:

function changeCanvasSize() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	gameCanvas.width = 600;
	gameCanvas.height = 800;

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, 0, 0);
	gameCanvas.getContext("2d").drawImage(avatarImage, 100, 50);
	gameCanvas.getContext("2d").drawImage(avatarImage, 200, 130);
	gameCanvas.getContext("2d").drawImage(avatarImage, 300, 270);
}

Check it out, skull party. We can also make the skull appear in a random place each time:

function changeCanvasSize() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	gameCanvas.width = 600;
	gameCanvas.height = 800;

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
}

Math.random() give you a random number between 0 and 1, so Math.random() * 100 gives you a random number between 0 and 100; this means that the coordinates of the new skull are anywhere between (0, 0) and (100, 100). Take a look!

But hold on – why is there only one skull at a time now? Is it something to do with it being a new function? Does the canvas get cleared every time you run a function?

No. The canvas is cleared every time you modify its height or width, even if you don’t change either. So, if we change our JS like so:

function changeCanvasSize() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
}

…then we can keep adding new skulls.

In fact, let’s change the name of the function to drawAvatar(), and tidy things up a bit:

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
}

Don’t forget to change the onclick attribute of canvas in your HTML:

<!DOCTYPE html>
<html>
	<head>
		<title>HTML5 Avoider Game</title>
		<script src="js/main.js"></script>
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<canvas id="gameCanvas" onclick="drawAvatar();" width="400" height="300"></canvas>
		<p>From <a href="http://active.tutsplus.com/tutorials/html5/learn-html5-with-this-simple-avoider-game-tutorial" rel="external">Learn HTML5 With This Simple Avoider Game Tutorial</a>.</p>
	</body>
</html>

Okay, now let’s get that avatar moving.


Adding Interactivity

I want to make the avatar follow the mouse. We can use the same principle that animators do: if we keep erasing the contents of the canvas, and then re-drawing the avatar at a different position, the avatar will appear to move. So all we have to do is keep redrawing the avatar at the mouse’s coordinates, and we’re set!

How do we do that, though?

A Grand Event

Judging by what we’ve done so far, you might guess that we’d add a onmousemove event attribute to the canvas (which would be triggered every time the user moved their mouse), then make it run drawAvatar(), but specifically at the mouse’s current coordinates. This is inspired, but unfortunately doesn’t really work, simply because it doesn’t offer an easy way to obtain the mouse’s coordinates.

However, it is very close to what we want to do! Take a look at this:

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);

	gameCanvas.addEventListener("mousemove", redrawAvatar);
}

This does roughly the same thing as the above suggestion; the redrawAvatar() function (which we haven’t written yet) will be called whenever the mouse moves over the canvas. But there’s one big difference.

Notice how we write redrawAvatar, rather than redrawAvatar() in the code above, whereas in our HTML page, we put drawAvatar() – with “parentheses” (round brackets) – in the onclick event attribute of our canvas. The full reason for that is a little complicated to go into now (though you’ll understand by the end of the series), but it has one very important upshot: it allows us to obtain the mouse’s coordinates.

When the mouse moves, the browser creates a new object – just like when we created a new Image in our JavaScript earlier. This object has certain attributes that have something to do with the thing that triggered its creation; in this case, because the mouse moved, it contains the coordinates of the mouse. Brilliant!

So how do we access it? Well, this new object (which is called a MouseEvent, for reasons that you might be able to guess) gets passed to the redrawAvatar() function. Er, but we haven’t written that yet, so let’s do that now. Add this code to your JS file:

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);

	gameCanvas.addEventListener("mousemove", redrawAvatar);
}

function redrawAvatar(mouseEvent) {

}

Aha – this time, the way we define the function is a little different: we’ve added the word mouseEvent in-between those parentheses. This is because we are expecting the browser to pass a MouseEvent object to our new function, just like when we passed the coordinates to the drawImage() function.

Since we’ve given it a name, we can access the attributes of this new object:

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);

	gameCanvas.addEventListener("mousemove", redrawAvatar);
}

function redrawAvatar(mouseEvent) {
	alert(mouseEvent.x);
}

Test this out; you’ll have to click the canvas before anything will happen, because it’s inside that function that we make the browser start paying attention to mouse movements.

You’ll notice that the dialog box only appears when the mouse moves over the canvas element. You might also notice something odd about the number: it’s too big! I’m getting numbers of over 900, even though the width of the canvas is only 400.

This is because mouseEvent.x gives the mouse’s x-position from the edge of the page, rather than the edge of the canvas. We can use mouseEvent.offsetX to get the mouse’s x-position from the edge of the canvas:

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);

	gameCanvas.addEventListener("mousemove", redrawAvatar);
}

function redrawAvatar(mouseEvent) {
	alert(mouseEvent.offsetX);
}

Much better!

So, to recap: addEventListener() makes the browser listen for certain events – such as the movement of the mouse – and then run a function when this event is “heard”. The browser creates a new object (like a MouseEvent), and passes it to that function.

It’s a little hard to wrap your head around, but don’t worry; we’ll be using it a lot, so you’ll get the hang of it!

Move Your Head

We’ve nearly got movement. In fact, I recommend you have a go at making the avatar follow the mouse on your own before reading further. You’ll probably come very close!

There’s one big thing that’ll trip you up, though: the word var – which, you’ll remember, you can use to set a shorthand – only “lasts” within the function in which it was defined.

This means that if you try to do, say:

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);

	gameCanvas.addEventListener("mousemove", redrawAvatar);
}

function redrawAvatar(mouseEvent) {
	gameCanvas.width = 400;
	alert(mouseEvent.offsetX);
}

…it won’t work, because gameCanvas means nothing outside of drawAvatar()!

So, if you didn’t get it the first time, have another go.

My code is here if you want to check yours (click the little triangle):

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);

	gameCanvas.addEventListener("mousemove", redrawAvatar);
}

function redrawAvatar(mouseEvent) {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
}

Tada! Oh, wait, dang, I forgot to erase the canvas by changing its width or height. Cool effect, but let’s try that again:

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);

	gameCanvas.addEventListener("mousemove", redrawAvatar);
}

function redrawAvatar(mouseEvent) {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.width = 400;
	gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
}

Try it out now. Success!

Wait, What Was That For?

When you take another look at your code in a few days’ time, you’re likely to have forgotten what a lot of it is for. In particular, I suspect you’ll forget why you need to resize the canvas.

Fortunately, there’s a way to remind yourself: comments.

Look at this:

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);

	gameCanvas.addEventListener("mousemove", redrawAvatar);
}

function redrawAvatar(mouseEvent) {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.width = 400;	//this erases the contents of the canvas
	gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
}

The browser ignores everything on the line after a //. This means you can write whatever you like there, and it won’t be run as code. It’s called an inline comment and is very important. To help get yourself into the habit of commenting your code, go through it now and write comments after each line that you think you might have trouble understanding after a few days’ break.

Commenting may seem like a waste of time. I think a lot of new programmers assume that when they first start out; it only takes one bad experience with trying to update your own, uncommented code (or worse: someone else’s!) to convince you of its worth, though :)

Hide the Mouse

At the moment, you’ve got a big stupid mouse cursor hovering over your avatar:

Learn HTML5 With This Simple Avoider Game Tutorial

We can fix this with a little CSS. Modify your stylesheet like so:

canvas {
	border: 1px solid black;
	cursor: none;
}

In most browsers, this will make your cursor disappear when it’s on top of the canvas… but not in Chrome.

Chrome doesn’t support cursor: none;, but it does allow you to replace the cursor with a PNG file of your choice. So, you can create a PNG that’s completely transparent, put it in your img folder, and use that, like so:

canvas {
	border: 1px solid black;
	cursor: url("../img/transparentcursor.png"), none;
}

(I’ve had to put ../ at the start of the URL because, in CSS, relative paths are relative to the folder of the CSS file, not the HTML file, and “..” says, “the folder above this one”. Also, I’ve put , none after this, because it means that if any browsers don’t support using PNGs for cursors, they’ll use the none attribute instead. Can you see why I wanted to avoid focusing on cross-browser compatibility?)

Unfortunately, this doesn’t work either, because if you use a completely transparent PNG, Chrome just shows a solid black rectangle instead. Thanks, Chrome.

So, instead, I’ve made a 1x1px PNG that’s almost transparent (the single pixel is white, with an opacity of 1%). You can download it here. Copy it to your img folder, then modify your CSS stylesheet:

canvas {
	border: 1px solid black;
	cursor: url("../img/almosttransparent.png"), none;
}

Test it out. It does work, after all that effort.


Make an Enemy

We’ve accomplished a lot so far, but our avoider game still doesn’t have anything to avoid! The last thing we’ll do, in this part of the series, is create an enemy.

We need an image to represent this. Draw whatever you like, but make sure that it’s roughly circular, and about 30x30px. I’m going to take my cue from FrozenHaddock again. He picked a smiley face for his game’s enemy; I’m not sure why, but I suspect it was a comment on the over-pervasiveness of smileys in modern conversation; a yearning for the days of emotions over emoticons, where poets would pour their hearts into a single sentence of text, rather than simply typing semicolon close-parenthesis ell oh ell. Or maybe it’s just because smiley faces are easier to draw. Regardless, here’s mine:

Learn HTML5 With This Simple Avoider Game Tutorial

Call yours enemy.png and put it in the img directory.

You can probably figure out how to draw this enemy (unmoving) on the canvas – if so, give it a shot! Once again, I recommend you do this before reading on.

Here’s my solution (click the little triangle):

function drawAvatar() {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();

	avatarImage.src = "img/avatar.png";
	gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);

	gameCanvas.addEventListener("mousemove", redrawAvatar);
}

function redrawAvatar(mouseEvent) {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();
	var enemyImage = new Image();

	avatarImage.src = "img/avatar.png";
	enemyImage.src = "img/enemy.png";
	gameCanvas.width = 400;		//this erases the contents of the canvas
	gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
	gameCanvas.getContext("2d").drawImage(enemyImage, 250, 150);
}

Your method might be different to mine – that’s okay, as long as it works! But for consistency, please copy my method into your code.

Note that I keep the var statements at the top of their respective functions. This isn’t strictly necessary, but it keeps things tidy, so I recommend it.

Besides that, nothing here should surprise you. There’s no particular significance to the coordinates (250, 150) that I’ve chosen.

Try it out!

Putting the “Avoid” in “Avoider Game”

We’re not going to worry about making the enemy move in this part of the tutorial; that topic deserves more space than I can afford it here. But we will check for a collision between the avatar and the enemy!

First, we’ll do something simpler: we’ll consider a certain area of the screen “off-limits” and pop up a dialog box if the avatar moves into that area.

Modify your redrawAvatar() function like so:

function redrawAvatar(mouseEvent) {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();
	var enemyImage = new Image();

	avatarImage.src = "img/avatar.png";
	enemyImage.src = "img/enemy.png";
	gameCanvas.width = 400;		//this erases the contents of the canvas
	gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
	gameCanvas.getContext("2d").drawImage(enemyImage, 250, 150);

	if (mouseEvent.offsetX < 100) {
		alert("Too far left!");
	}
}

Try it out. If your avatar goes too far to the left side of the screen, the dialog box appears.

Let’s take a closer look at the code:

if (condition) {
	outcome;
}

The if statement is a way of checking whether something has happened. It’s made up of two parts: a condition, inside the parentheses, and a result, inside the curly braces. If the condition is true, then the outcome is called.

In our case, the condition is mouseEvent.offsetX < 100. The < symbol means "less than", and remember that mouseEvent.offsetX is the cursor's horizontal distance from the left edge of the canvas. So, this is checking whether the cursor is within 100 pixels of the left edge of the canvas. If it is, then...

...the outcome is run. And in our case, the outcome is alert("Too far left!");, the dialog box function we've used a number of times.

Make sense? Okay, good, because I'm going to make it more complicated:

function redrawAvatar(mouseEvent) {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();
	var enemyImage = new Image();

	avatarImage.src = "img/avatar.png";
	enemyImage.src = "img/enemy.png";
	gameCanvas.width = 400;		//this erases the contents of the canvas
	gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
	gameCanvas.getContext("2d").drawImage(enemyImage, 250, 150);

	if (mouseEvent.offsetX < 100 || mouseEvent.offsetY < 100) {
		alert("Too far left, or too far up!");
	}
}

In this code, we've introduced a new operator: ||. || means (and is pronounced) "or". The if statement therefore reads:

"If the mouse is within 100 pixels of the left edge of the canvas, OR the mouse is within 100 pixels of the top edge of the canvas, show the dialog box."

Try this out, and you'll see that you can't get anywhere near the top or the left of the canvas.

How about this:

function redrawAvatar(mouseEvent) {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();
	var enemyImage = new Image();

	avatarImage.src = "img/avatar.png";
	enemyImage.src = "img/enemy.png";
	gameCanvas.width = 400;		//this erases the contents of the canvas
	gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
	gameCanvas.getContext("2d").drawImage(enemyImage, 250, 150);

	if (mouseEvent.offsetX > 150 && mouseEvent.offsetX < 250) {
		alert("Stay out of the middle!");
	}
}

The && operator means (and is pronounced) "and", and > means "greater than". So, our if statement now reads:

"If the mouse is more than 150 pixels away from the left edge of the canvas AND the mouse is less than 250 pixels away from the left edge of the canvas, show the dialog box."

Test it out, and you'll see that we effectively have an invisible "stripe" down the middle of the canvas where we can't put our mouse.

We're not restricted to just using two clauses at once; check this out:

function redrawAvatar(mouseEvent) {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();
	var enemyImage = new Image();

	avatarImage.src = "img/avatar.png";
	enemyImage.src = "img/enemy.png";
	gameCanvas.width = 400;		//this erases the contents of the canvas
	gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
	gameCanvas.getContext("2d").drawImage(enemyImage, 250, 150);

	if (mouseEvent.offsetX > 150 && mouseEvent.offsetX < 250 && mouseEvent.offsetY > 100 && mouseEvent.offsetY < 200) {
		alert("Stay out of the center!");
	}
}

We've now effectively drawn a 100x100px box, in the centre of the canvas, where we can't put our mouse.

Can you see where we're going with this?

Rather than a 100x100px box in the middle of the canvas, we should use a 30x30px box positioned where our enemy is.

This is the last thing we're going to do in this part of the tutorial, so once again I recommend you have a go yourself. It's pretty fiddly - you'll probably want to get some paper out to draw the avatar and the enemy and label some coordinates - but you can do it if you use what you've learned so far.

My solution is below.

function redrawAvatar(mouseEvent) {
	var gameCanvas = document.getElementById("gameCanvas");
	var avatarImage = new Image();
	var enemyImage = new Image();

	avatarImage.src = "img/avatar.png";
	enemyImage.src = "img/enemy.png";
	gameCanvas.width = 400;		//this erases the contents of the canvas
	gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
	gameCanvas.getContext("2d").drawImage(enemyImage, 250, 150);

	//my avatar is 30px wide and the enemy is at x=250, so I have to check whether mouseEvent.offsetX is within 30px
	//either side of x=250 (i.e., from 220 to 280)
	//similarly, since my avatar is 33px tall, I have to check whether mouseEvent.offsetX is within 33px ABOVE y=150
	//but since enemy is only 30px tall, I also check whether mouseEvent.offsetX is within 30px BELOW y=150
	//therefore, I check from (117 to 180)
	if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
		alert("You hit the enemy!");
	}
}

Try it out here!


Next Time

That's it for the first part of the tutorial. In the next part, we'll get that enemy moving, and we'll add more of them, so that this can start to be a real game!

In the meantime, why not experiment with what you've learned? You could try adding multiple (unmoving) enemies yourself, perhaps with different graphics. Or you could add several avatars on screen at once, all following the mouse in different ways. What happens if you use something like mouseEvent.offsetX + 100 or 300 - mouseEvent.offsetY in your call to gameCanvas.getContext("2d").drawImage()?

I hope you've enjoyed this so far. If anything's not clear, please ask about it in the comments :)

(One other quick note: at the moment, your code should work just fine on your own computer, but won't work if uploaded to the web. My demos work online, because I did a sneaky trick. Don't worry, I'll explain how to solve this in a future part of the tutorial.)



View full post on Activetuts+

Aug 11, 2011 Posted on Aug 11, 2011 in Hints and Tips | 10 comments

Review: SmartMouth for Flash Makes Lip-Syncing Simple

I’m neither an artist nor an animator, and yet I was able to lip-sync an audio track in next to no time, all thanks to SmartMouth by Justin Putney. This Flash Professional extension really impressed me with how quickly it was able to automate an otherwise extremely tedious task. Read on to see how it can make animating your cutscenes so much easier.


First Impressions

SmartMouth comes in a standard MXP package, like most Flash Professional extensions, so it was a snap to install: I just double-clicked the MXP and followed the on-screen instructions. (It’d be the same for any version of Flash from CS3 upwards, though for CS3 itself you must have installed the Extension Manager.)

Once I installed it and restarted Flash, I could access the main panel via Commands | Lip Sync with SmartMouth:

SmartMouth main panel

The Help document can be brought up by clicking the question mark button; this does a great job of explaining the separate elements of the panel, but — call me biased — I felt it could also have used a brief tutorial walking me through how to use the tool. Still, there’s a detailed tutorial over on the Adobe Developer Connection, and the process is pretty simple anyway:

First, I imported a sound track (I picked this public domain reading of one of Aesop’s Fables, from LibriVox), put it on its own layer, and set its Sync to Stream.

Next, I created a new layer for the mouth to go on. Like I said, I’m not an artist, but fortunately we have a free Lip Sync Assets pack in the Activetuts+ archives, so I downloaded and imported that. I dragged and dropped each symbol onto a frame in my MouthShapes layer.

Then I re-opened the SmartMouth panel; it had taken a guess at the layers I wanted to use for audio and animation, so all I had to do was choose the shapes that corresponded to each phoneme:

SmartMouth main panel -- populated

As you can see, it picked a Start Frame and an End Frame for me, so all I had to do was click Tell me, SmartMouth. This kicks off the audio analyzer, which plays the whole audio track through (visualizing it as it goes):

SmartMouth Audio Analyzer

After that, there’s a brief wait while it adds the keyframes for each mouth sound. I picked a 45 second sound file, which took up about a thousand frames (at 24fps), and SmartMouth figured out which mouth sounds went where — and actually placed the keyframes — within twenty seconds:

SmartMouth modifies the timeline

All I had to do then was remove the original mouth shapes from the timeline, and add a “grin” to the end (okay, technically that last one was optional). Check out the results for yourself:

Click to start the audio and animation.

I’m impressed!


Room for Improvement

I did come across a couple of bugs while using SmartMouth. When I entered my registration key, the “Success” dialog got stuck in a loop, and kept reappearing no matter how many times I hit OK. Then, later, I tried deleting all the mouth frames which SmartMouth had placed and running it again; this made it run a lot slower, and in fact it took longer than the 60 second time limit Flash imposes, making it crash without finishing its job.

Still, neither bug was a big problem, since SmartMouth has a kind of “emergency exit”: right-click the main panel and click EXIT, and it’ll shut down, putting you back in control. Plus, if the audio is too long, you can work in chunks of a few hundred frames at a time by changing the Start and End Frame options.

I mentioned, the Help docs are well-written — but I would have liked to see tool tips on the various buttons within the panel. It’s not immediately obvious what the buttons next to End Frame are for, nor what Mode or Limit To actually do, without reading up on them. Even “Tell me, SmartMouth” doesn’t suggest a command that will automatically place symbols in the timeline. But these are just nitpicks; once you’ve used the options, you’ll know what they do.

My one major gripe was that, even though I placed the mouth shape symbols in different places around the stage, SmartMouth aligned them all when syncing to the audio (I think the mouth shape for the letter O is out of place in the SWF demo above). However, this proved to be my mistake: if I’d created a new symbol on the MouthShapes layer, and placed the individual mouth symbols inside that symbol, SmartMouth would have preserved my positionings.


My Verdict

After Ian finished Animating the Envato Community Podcast, he told me that a tool like SmartMouth would have saved him a lot of time and tedium. (Actually, he used rather more excited terms than that.) I can see why.

In that video, there were several different people talking in turn, so there were different mouths that needed to be animated. SmartMouth doesn’t have an interface for doing this specifically, but it would be pretty simple to use it for that. Either:

  • separate the speakers’ voices into separate tracks on separate layers and run SmartMouth once per track,
  • use the Start and End Frame boxes to isolate the section of the track corresponding to one character at a time, or
  • run it once for each character and simply delete the frames that don’t match the character who’s talking.

Although SmarthMouth’s most instantly impressive feature is its ability to put the mouth symbols on the stage in sync with the vocal track, this isn’t strictly necessary. If you prefer, you can tell SmartMouth just to create a new layer with labels corresponding to each phoneme in the vocals, so you can put the graphics in manually without having to keep scrubbing the timeline to see what sound you’re supposed to be imitating. This would be useful for frame-by-frame animation, or a scene with a lot of motion.

It’s also possible to make SmartMouth export the phoneme data to an XML file; this could then be used in another platform, like Unity, or even loaded into a SWF with AS3 so that you could animate a custom avatar’s mouth dynamically. (From what I hear, Justin is working on a version of the tool specifically for that purpose.)

Overall, I highly recommend SmartMouth if you need to do any lip-syncing in Flash. The basic functionality it amazing by itself, and the extra features push it over the edge.

SmartMouth is available for purchase at the Ajar Productions website; prices start at $49.99 for a single seat, with discounts if multiple seats are bought at once.



View full post on Activetuts+

Page 1 of 512345»
search search search search search
Find an Article
Categories
  • Flash Video Training
  • Hints and Tips
  • Recommended
Please Support Our Sponsors
Recent Posts
  • The Math and ActionScript of Curves: Drawing Quadratic and Cubic Curves
  • Weekend Lecture: Understanding Games, a Flash Game About Game Design
  • Weekend Lecture: Understanding Games, a Flash Game About Game Design
  • Workshop Coding Challenge: Fix This Breakout Game
  • Enable the Latest AIR SDK in Flash Professional CS5.5+
Tag Cloud
2011 ActionScript Active Activetuts+ Adobe animation Basic Basix Best Build Button Character Create Creating Critique Custom design Effect Effects Files Flash from Game Guide HTML5 Introduction Macromedia Motion Muzzle part Player Premium Professional Quick Silverlight Simple Text Tool Tutorial Tuts+ Tween Using Video website Workshop
About Our Site:

Hey there and welcome to "Flash Video Training Source", a resource for anybody interested in learning more about Adobe's great tool. We feature educational videos, which will help you master Adobe Flash and help you get to know all of its features. We at "Flash Video Training Source" believe that video training and video... more

Why don't you follow us on Twitter and get the latest video tutorials twitted to your account. Just click on the floating twitter bar to your right!

Go Back In Time
May 2012
M T W T F S S
« Apr    
 123456
78910111213
14151617181920
21222324252627
28293031  
Pretty Blank Box
top

Blogroll

  • Development Blog
  • Documentation
  • Plugins
  • Suggest Ideas
  • Support Forum
  • Themes
  • WordPress Planet

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

Archives

  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • June 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • January 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010
  • June 2010
  • May 2010
  • April 2010
Powered by WordPress  |  Designed by Elegant Themes  |  Lightning Fast Hosting by Site 5 Hosting