logo
468x60-2-495


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

Creating “Flux”: A Simple Flash Game With a Gravity Mechanic

In this tutorial, I’ll explain the major steps and workflow for creating a simple space survival game, based on the gravity mechanic explained in a previous tutorial. This game is written in AS3 using FlashDevelop.


Play the Game

Use the left and right arrow keys to manoeuvre your ship, the up and down arrow keys to increase or reduce the size of the magnetic field it produces, and the space bar to reverse the polarity. Collect the white crystals to increase your fuel supply – but avoid the red ones, because they use it up. Don’t hit a rock, or it’s game over!

In this tutorial, we won’t actually create the full game displayed above; we’ll just get started on it, by making a very simple version with primitive graphics and just one type of object. However, by the end, you should have learned enough to be able to add the other features yourself!

The game itself is very simple in its current state. Check back later today for a look at what we could do to improve the game! This tutorial is going to focus on the code and math required to build this demo.


Let’s Get Started!

Set up a new AS3 project in FlashDevelop, and set its dimensions to 550x600px.

 package
{
	[SWF(width = "550", height = "600")]

	public class Main extends Sprite
	{

	}
}

Step 1: Identifying the Game Objects

There are six objects in particle that you can identify from playing the game above:

  • Energy supply – represented by an white oval shape object
  • Asteroid – represented by a rock-like object
  • Energy consumer – represented by a red star bounded with green light.
  • Stars – the background
  • Range indicator – represented by a white circle
  • Ship – player object

Of course you can add in any other object to make the game more interactive or add a new feature. For this tutorial we’ll just make


Step 2: The Energy Class

From the objects we identified, four of them actually work in exactly the same way: by falling from top to bottom.

They are:

  • Stars
  • Energy supply
  • Energy consumer
  • Asteroid

In this tutorial, we’re only going to make the “energy supply” objects, out of the four above. So let’s begin by creating these objects and making them fall down, with a random spawning position and speed.

Start by creating an Energy class:

	package
	{
		import flash.display.MovieClip;
		import flash.events.Event;

		public class Energy extends MovieClip
		{
			private var rSpeed:Number = 0;

			public function Energy(speed:Number)
			{
				graphics.beginFill(0x321312);
				graphics.drawCircle(0, 0 , 8);

				addEventListener(Event.ENTER_FRAME, move);	

				rSpeed = speed;
			}

			// runs every frame
			public function move(e:Event):void
			{
				this.y += rSpeed;
				//rotation speed is linked to moving speed
				this.rotation += rSpeed / 8;
			}
		}
	}

Step 3: The StageController Class

This class will eventually control most of the aspects of our game, including the player movement and the game loop.

For now, though, we’ll just use it as a place to store a reference to the stage.

Create the class:

package
{
	import flash.display.Stage;

	public class StageController
	{
		public static var STAGE:Stage;

		public function StageController(stg:Stage)
		{
			// we will pass the stage from the Main class
			STAGE = stg;
		}
	}
}

We’re going to pass a reference to the stage to this class from our Main class (which is automatically created by FlashDevelop as the starting class for our game). This will allow us to add display objects to the display list from this class.


Step 4: Update The Main Class

We’ll now create an instance of StageController within Main and pass it a reference to the stage:

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

	[SWF(width = "550", height = "600")]

	public class Main extends Sprite
	{
		private var stageController:StageController;

		public function Main():void
		{
			stageController = new StageController(stage);
		}
	}
}

Step 5: Introducing a Manager Class

To avoid the StageController class becoming too much of a mess, we’ll use separate classes to manage each object.

Each manager class will contain all the functions that relate to, and interact with, a particular object. Here’s the EnergyManager class:

package
{
	import flash.display.MovieClip;

	public class EnergyManager
	{
		public var energy:Energy;
		// this Vector will store all instances of the Energy class
		private var energyList:Vector.<Energy>	

		public function EnergyManager()
		{
			energyList = new Vector.<Energy>;
		}
	}
}

So far the class contain no other functions; we will add them in later.


Step 6: Creating Energy

Add below function for creating energy, this is just a function, we will be calling the function later from StageController Class:

	public function createEnergy(number:int):void
	{
		for (var i:int = 0; i < number; i++) {		

			energy = new Energy(4);				

			StageController.STAGE.addChild(energy);

			energyList.push(energy);				

			energy.x = Calculation.generateRandomValue(30, 520);
			energy.y = Calculation.generateRandomValue( -150, -20);
		}
	}

We create a new energy supply with a speed of 4, add it directly to the stage via the StageController, add it to the Vector of all energy objects that we just created, and set its position to a random point within certain bounds.

Editor’s Note: I’m a little uncomfortable with adding a display object directly to the stage like that, although of course it does work. One alternative would be to create a function within StageController that handles this for us.

The Calculation.generateRandomValue(#, #) is a static function we haven’t written yet, so let’s do that now. Create a new class called Calculation and add this function:

	public static function generateRandomValue(min:Number, max:Number):Number
	{
		var randomValue:Number = min + (Math.random() * (max - min));

		return randomValue;
	}

This function will generate a random number between the two values passed to it. For more information on how it works, see this Quick Tip. Since this is a static function, we don’t need to create an instance of Calculation in order to call it.


Step 7: Spawning Energy

Let’s set a timer that defines the interval for each spawning. This code goes in StageController‘s constructor function:

energyM = new EnergyManager;

var spawnTimer:Timer = new Timer(3000, 0);
spawnTimer.addEventListener(TimerEvent.TIMER, spawnEnergy);
spawnTimer.start();

So, every three seconds, the timer will call spawnEnergy(). Let’s write that function now:

private function spawnEnergy(e:TimerEvent):void
	{
		energyM.createEnergy(4);    // create 4 energies
	}

Step 8: Creating Player

Let’s use another, bigger circle to represent the player. Feel free to import an image to use instead:

public function Player()
		{
			graphics.beginFill(0x7ebff1);
			graphics.drawCircle(0, 0, 20);

Add this code to StageController to add the player to the screen:

// in the variable definitions
public var player:Player;
// in the constructor function
player = new Player;
STAGE.addChild(player);
player.x = 275;
player.y = 450;

So far we should have a few energy supplies falling few seconds, and the player appearing in the middle of the screen:

playerandenergy.

Step 9: Moving the Player

There are basically two ways to apply movement:

  1. Using Boolean (true/false) values – true = moving, false = not moving. When the right arrow key is pressed, the value for “moving right” will change to true. In each frame update, “moving right” is true, we increase the object’s x-value.
  2. Using direct update each frame – when the right arrow key is pressed, an object is told to move right immediately, by increasing its x-value.

The second method does not lead to smooth movement when the key is continuously pressed, but the first method does – so we shall use the first method.

There are three simple steps to doing this:

  1. Create two Boolean variables, one for moving right and one for moving left.
    	private var moveRight:Boolean = false;
    	private var moveLeft:Boolean = false;
    	
  2. Toggle the Boolean when keys are pressed or released:
    		STAGE.addEventListener(Event.ENTER_FRAME, update);
    		STAGE.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler);
    		STAGE.addEventListener(KeyboardEvent.KEY_UP, KeyUpHandler);
    	}
    
    	private function KeyDownHandler(e:KeyboardEvent):void
    	{
    		if (e.keyCode == Keyboard.RIGHT) {
    			moveRight = true;
    		}
    		if (e.keyCode == Keyboard.LEFT) {
    			moveLeft = true;
    		}
    		if (e.keyCode == Keyboard.SPACE) {
    			if (space == true) {
    				space = false;
    			}else if (space == false) {
    				space = true;
    			}
    		}
    	}
    
    	private function KeyUpHandler(e:KeyboardEvent):void
    	{
    		if (e.keyCode == Keyboard.RIGHT) {
    			moveRight = false;
    		}
    		if (e.keyCode == Keyboard.LEFT) {
    			moveLeft = false;
    		}
    	}
    	
  3. Based on these Booleans, actually move the player every frame:

    Don’t forget to first create a function listen from the enter frame event, “updating” :

    //call this function every frame
    private function update(e:Event):void
    	if (moveRight == true) {
    		player.x += 6;
    	}
    	if (moveLeft == true) {
    		player.x -= 6;
    	}
    	

    Keep the player within the bounds of the screen:

    	if (player.x >= 525) {
    		moveRight = false;
    	}
    	if (player.x <= 20) {
    		moveLeft = false;
    	}
    	

Here’s how all that looks, in place:

package
{
    import flash.display.MovieClip;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.ui.Keyboard;
    import flash.utils.Timer;
    import flash.events.KeyboardEvent;

    public class StageController
    {
        public static var STAGE:Stage;    // A variable that store Stage class type.
        public var player:Player;

        private var energyM:EnergyManager;

        private var moveRight:Boolean = false;
        private var moveLeft:Boolean = false;
        private var space:Boolean = true;

        private var returnedPower:int = 0;

        private var scoreText:Text;
        private var totalScore:int=0;
        private var score:Text;

        public function StageController(stg:Stage)   // Passing the stage from calling.
        {
            STAGE = stg;        // store "stage" passed to STAGE (we will pass from Main class).
            scoreText = new Text("Score :");
            STAGE.addChild(scoreText);

            energyM = new EnergyManager;

            var spawnTimer:Timer = new Timer(3000, 0);
            spawnTimer.addEventListener(TimerEvent.TIMER, spawnEnergy);
            spawnTimer.start();

            player = new Player;
            STAGE.addChild(player);
            player.x = 275;
            player.y = 450;

            STAGE.addEventListener(Event.ENTER_FRAME, update);
            STAGE.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler);
            STAGE.addEventListener(KeyboardEvent.KEY_UP, KeyUpHandler);
        }

	private function KeyDownHandler(e:KeyboardEvent):void
	{
		if (e.keyCode == Keyboard.RIGHT) {
			moveRight = true;
		}
		if (e.keyCode == Keyboard.LEFT) {
			moveLeft = true;
		}
		if (e.keyCode == Keyboard.SPACE) {
			if (space == true) {
				space = false;
			}else if (space == false) {
				space = true;
			}
		}
	}

	private function KeyUpHandler(e:KeyboardEvent):void
	{
		if (e.keyCode == Keyboard.RIGHT) {
			moveRight = false;
		}
		if (e.keyCode == Keyboard.LEFT) {
			moveLeft = false;
		}
	}

	private function update(e:Event):void
	{
		if (player.x >= 525) {
			moveRight = false;
		}
		if (player.x <= 20) {
			moveLeft = false;
		}
		if (moveRight == true) {
			player.x += 6;
		}
		if (moveLeft == true) {
			player.x -= 6;
		}
	}
    }
}

Step 10: Collision Detection

We will need to check for collisions between each energy object and the player. (If you develop the game further, you’ll need to check this for asteroids and energy consumers, but not for stars.)

The best place to handle these checks is inside the EnergyManager, triggered every frame by the StageController.

One thing to consider: the collision checks will be between two circles, so hitTestObject() is not ideal. Instead, we’ll be using the method explained in this tutorial.

We can write the function as below:

	public function checkCollision(p:Player):int
	{
		// energy transferred due to collision
		var energyTransfer:int = 0;

		for (var i:int = 0; i < energyList.length; i++) {
			var energyS:Energy = energyList[i];

			var newX:Number = p.x - energyS.x;
			var newY:Number = p.y - energyS.y;

			var distance:Number = Math.sqrt(newX * newX + newY * newY);

			if (distance <= 28) {
				StageController.STAGE.removeChild(energyS);
				energyList.splice(i, 1);
				// for this simple game, we'll always transfer 1 unit
				// but you could alter this based on speed of collision
				// or any other factor
				energyTransfer = 1;
			}
		}
		return energyTransfer;
	}
  • Line 32: note that we pass in a reference to the player, so that we can access its position.
  • Line 38: EnergyS is short for Energy Supply.
  • Line 40 & 41: finding the difference in x- and y-coordinates between the player and the energy supply we are currently checking.
  • Line 43: calculate the distance between the objects via Pythagorus.
  • Line 45: check for collision; 28 is the sum of the two objects’ radii (player radius is 20, energy radius is 8).
  • Line 46 & 47: remove energy supply from screen and from Vector.
  • Line 51: add a maximum of one unit of energy per frame.

You could alter Line 51 to energyTransfer += 1, to allow the player to absorb more than one energy object at once. It’s up to you – try it out and see how it affects the game.


Step 11: Call Collision Detection Routine

We need to check for collisions every frame, so we should call the function we just wrote from StageController.update().

First, we need to create an integer variable to store the energy transfer value from the collision detection function. We’ll use this value for increasing the ship’s energy and adding to the player’s score.

private var returnedPower:int = 0;
returnedPower = energyM.checkCollision(player);

Step 12: Newton’s Law of Gravitation

Before we go into creating the game mechanic for the ‘Push’ and ‘Pull’ function of the ship, I would like to introduce the physics concept on which the mechanic is based.

The idea is to attract the object towards the player by means of a force. Newton’s Law of Universal Gravitation gives us a great (and simple) mathematical formula we can use for this, where the force is of course the gravitational force:

G is just a number, and we can set it to whatever we like. Similarly, we can set the masses of each object in the game to any values that we like. Gravity occurs across infinite distances, but in our game, we’ll have a cut-off point (denoted by the white circle in the demo from the start of the tutorial).

The two most important things to note about this formula are:

  • The strength of the force depends on the square of the distance between the two objects (so if the objects are twice as far away, the force is one-quarter as strong).
  • The direction of the force is along the direct line connecting the two objects through space.

Step 13: Revising Math Concepts

Before we start coding the game mechanics for the ‘Push’ and ‘Pull’ function, let’s be clear on what we want it to do:

frameWork

Essentially, we want A (the player) to exert a certain force on B (a crystal), and move B towards A based on that force.

We should revise a few concepts:

  • Flash works in radians rather than degrees.
  • Flash’s coordinate system has its y-axis reversed: going down means an increase in y.
  • We can get the angle of the line connecting A to B using Math.atan2(B.y - A.y, B.x - A.x).
  • We can use trigonometry to figure out how much we need to move B along each axis, based on this angle and the force:
    • B.x += (Force*Math.cos(angle));
    • B.y += (Force*Math.sin(angle));
  • We can use Pythagorus’s theorem to figure out the distance between the two objects:

For more information, see the tutorials Gravity in Action and Trigonometry for Flash Game Developers.


Step 14: Implementing Push and Pull

Based on the previous explanation, we can come up with an outline for our code that attracts each crystal to the ship:

  1. Find the difference in x and y between the ship and a given crystal.
  2. Find the angle between them, in radians.
  3. Find the distance between them, using Pythagorus.
  4. Check whether object is within the ship’s gravitational field.
  5. If so, calculate the gravitational force, and…
  6. …apply the force, changing the x and y values of the crystal.

Sample Code:

	public function gravityPull(p:Player): void
	{
		for (var i:int = 0; i < energyList.length; i++) {
			var energyS:Energy = energyList[i];

			var nX:Number = (p.x - energyS.x);
			var nY:Number = (p.y - energyS.y);

			var angle:Number = Math.atan2(nY, nX);

			var r:Number =  Math.sqrt(nX * nX + nY * nY);

			if (r <= 250) {
				var f:Number = (4 * 50 * 10) / (r * r);
				energyS.x += f * Math.cos(angle);
				energyS.y += f * Math.sin(angle);
			}
		}
	}
  • Line 53: get a reference to the player.
  • Line 55: we loop through each energy object.
  • Line 61: find the angle between the ship and the energy.
  • Line 63: find the distance between them, too.
  • Line 65: check whether the energy is within the ship’s force field.
  • Line 67: use the formula:
    • 4 = G, the “gravitational constant” I’ve chosen.
    • 50 = m1, the mass of the ship player.
    • 10 = m2, the mass of the energy object.
  • Line 69: apply movement.

Here’s a timelapse showing how this looks:

Note that the energy moves faster the closer it gets to the ship, thanks to the r-squared term.

We can implement the pushing function just by making the force negative:

	public function gravityPull(p:Player): void
	{
		for (var i:int = 0; i < energyList.length; i++) {
			var energyS:Energy = energyList[i];

			var nX:Number = (p.x - energyS.x);
			var nY:Number = (p.y - energyS.y);

			var angle:Number = Math.atan2(nY, nX);

			var r:Number =  Math.sqrt(nX * nX + nY * nY);

			if (r <= 250) {
				var f:Number = (4 * 50 * 10) / (r * r);
				energyS.x -= f * Math.cos(angle);
				energyS.y -= f * Math.sin(angle);
			}
		}
	}

Here the object moves more slowly as it gets further away from the player, since the force gets weaker.


Step 15: Apply the Mechanic

Of course that you will need this function to be run each frame by StageController – but before that, we will need to use a Boolean function to toggle between the two functions:

private var space:Boolean = true;  //called space because hitting space toggles it

We are going to use true for ‘Push’ and false for ‘Pull’.

Inside KeyDownHandler():

	if (e.keyCode == Keyboard.SPACE) {
		if (space == true) {
			space = false;
		} else if (space == false) {
			space = true;
		}
	}

Afterwards, you will have to check the Boolean each frame. Add this to update():

	if (space == true) {
		energyM.gravityPull(player);
	}
	if (space == false) {
		energyM.gravityPush(player);
	}

Step 16: Modification

You might find that the movement doesn’t look so nice. This could be because the force is not quite ideal, or because of the r-squared term.

I’d like to alter the formula like so:

var f:Number = (0.8 * 50 * 10) / r;

As you can see, I’ve reduced the value of “G” to 0.8, and changed the force to depend simply on the distance between the objects, rather than the distance squared.

Try it out and see if you enjoy the change. You can always alter it however you like.


Step 17: The Text Class

We will need to show some text on the screen, for showing the score and the ship’s remaining power.

For this purpose, we’ll build a new class, Text:

package
{
	import flash.display.MovieClip;
	import flash.text.TextField;
	import flash.events.Event;
	import flash.text.TextFormat;

	import flash.text.TextFormatAlign;

	public class Text extends MovieClip
	{
		public var _scoreText:TextField= new TextField();

		public function Text(string:String)
		{
			var myScoreFormat:TextFormat = new TextFormat(); //Format changeable
			myScoreFormat.size = 24;		

			myScoreFormat.align = TextFormatAlign.LEFT;
			myScoreFormat.color = (0x131313);

			_scoreText.defaultTextFormat = myScoreFormat;

			_scoreText.text = string;

			addChild(_scoreText);
		}

		public function updateText(string:String)
		{
			_scoreText.text = string;
		}
	}
}

It’s very simple; it’s basically a MovieClip with a text field inside.


Step 18: Adding Power for Player

To give the game some challenge, we’ll make the ship’s power get used up slowly, so that the player has to collect energy objects in order to recharge.

To make the ship’s power appear on the ship itself, we can simply add an instance of Text to the ship object’s display list.

Declare these variables within the Ship class:

public var totalPower:Number = 100;  // ship starts with this much power
private var powerText:Text;

We’ll need to keep the amount of power (both stored and displayed) updated every frame, so add this to the constructor:

addEventListener(Event.ENTER_FRAME, updatePower);

Here’s the actual updatePower() function:

	private function updatePower(e:Event):void
		{
			// add a new text object if it doesn't already exist
			if (!powerText) {
				powerText = new Text(String(int(totalPower)));
				addChild(powerText);
				powerText.x -= 20;			//Adjust position
				powerText.y -= 16;
			}

			// fps = 24, so this makes power decrease by 1/sec
			totalPower -= 1 / 24;
			powerText.updateText(String(int(totalPower)));
		}

The power will decrease every frame by 1/24th of a unit, meaning it’ll decrease by one full unit every second.


Step 19: Make Energy Increase Power

When the ship collides with an energy object, we want it to increase its power.

In StageController.update(), add the highlighted line:

returnedPower = energyM.checkCollision(player);
player.totalPower += returnedPower;

Remember you can alter how much power is returned in the EnergyManager.checkCollision() function.


Step 20: Setting Up the Score

Again, we will need the text class. This time, we’ll display “Score” and then the value.

Here, we will need three more variables:

  • The “Score” text.
  • The score value text.
  • A variable to store the actual score.

Declare these in StageController class:

private var scoreText:Text;
private var totalScore:int = 0;
private var score:Text;

In the constructor, add this code:

scoreText = new Text("Score :");
STAGE.addChild(scoreText);

if (!score) {
	STAGE.removeChild(score);
	score = null;
}

score = new Text(String(totalScore));
STAGE.addChild(score);
score.x = scoreText.x + 100;   //Positioning it beside the "Score : " Text.
score.y += 2;

Now, in the update() function, add this:

score.updateText(String(totalScore));

That’s it – we’ve created a basic version of the above game!

Take a look (you may need to reload the page):


Extra Features and Polishing

Space Background

Maybe you would also like a background with an embedded image and stars. Add this to your Main class:

[Embed(source = "/../lib/SpaceBackground.jpg")]	//embed
		private var backgroundImage:Class; //This line must come immediately after the embed

		private var bgImage:Bitmap = new backgroundImage();
		private var numOfStars:int = 70;

Now create the Star class:

package assets
{
	import flash.display.MovieClip;
	import flash.events.Event;

	public class Star extends MovieClip
	{
		private var speed:Number;

		public function Star(alpha:Number, size:Number, speed1:Number)
		{
			graphics.beginFill(0xCCCCCC);
			graphics.drawCircle(0, 0, size);

			this.addEventListener(Event.ENTER_FRAME, moveDown);
			speed = speed1;
		}

		private function moveDown(e:Event):void
		{
			this.y += speed;

			if (this.y >= 600) {
				this.y = 0;
			}
		}
	}
}

In the Main() constructor, add this to create the stars:


for (var i:int = 0; i < numOfStars; i++) {
		createStars();
}

Here’s the actual createStars() function:


private function createStars():void
{
	var star:Star = new Star(
		Math.random(),
		Calculations.getRandomValue(1, 2),
		Calculations.getRandomValue(2, 5)
	);  //random alpha, size and speed

	addChild(star);

	star.x = Calculations.getRandomValue(0, 550);
	star.y = Calculations.getRandomValue(0, 600);
}

With random alpha, size, position, and speed, a pseudo-3D background can be generated.

Range indicator

A range indicator circle can be made by simply creating another circle and adding it to the ship’s display list, just like how you added the power indicator text. Make sure the circle is centred on the ship, and has a radius equal to the ship’s push/pull range.

Add transparancy (alpha value) to the circle with the below code:

			graphics.beginFill(0xCCCCCC, 0.1);

Try adding extra controls that make the range increase or decrease when the up and down arrow keys are pressed.


Conclusion

I hope you enjoyed this tutorial! Please do leave your comments.



View full post on Activetuts+

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&lt;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&lt;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+

Page 1 of 612345...»Last »
search search search search search
Find an Article
Categories
  • Flash Video Training
  • Hints and Tips
  • Recommended
Please Support Our Sponsors
Recent Posts
  • Tuts+ Community Meetup in New York!
  • HTML5 Canvas Optimization: A Practical Example
  • Recreate the Cover Flow Effect Using Flash and AS3
  • Drawing Activetuts+ to a Close
  • Intro to Dart: Creating a Marquee
Tag Cloud
2011 ActionScript Active Activetuts+ Adobe animation Basic Basix Best Build Button Character Code 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+ 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
June 2013
M T W T F S S
« Jul    
 12
3456789
10111213141516
17181920212223
24252627282930
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

  • July 2012
  • June 2012
  • 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