logo
468x60-2-495


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

Learn CreateJS by Building an HTML5 Pong Game

The web moves fast – so fast that our original EaselJS tutorial is already out of date! In this tutorial, you’ll learn how to use the newest CreateJS suite by creating a simple Pong clone.


Final Result Preview

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

The PONG game

Click to play

This tutorial is based on Carlos Yanez’s Create a Pong Game in HTML5 With EaselJS, which in turn built on his Getting Started With EaselJS guide. The graphics and sound effects are all taken from the former tutorial.


Step 1: Create index.html

This will be our main index.html file:

<!DOCTYPE html>
<html>
	<head>
		<title>Pong</title>

		<style>/* Removes Mobile Highlight */ *{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style>

		<script src="http://code.createjs.com/easeljs-0.4.2.min.js"></script>
		<script src="http://code.createjs.com/tweenjs-0.2.0.min.js"></script>
		<script src="http://code.createjs.com/soundjs-0.2.0.min.js"></script>
		<script src="http://code.createjs.com/preloadjs-0.1.0.min.js"></script>
		<script src="http://code.createjs.com/movieclip-0.4.1.min.js"></script>
		<script src="assets/soundjs.flashplugin-0.2.0.min.js"></script>
		<script src="Main.js"></script>

	</head>
	<body onload="Main();">
		<canvas id="PongStage" width="480" height="320"></canvas>
	</body>
</html>

As you can see, it’s pretty short and consists mainly of loading the CreateJS libraries.

Since the release of CreateJS (which basically bundles all the separate EaselJS libraries) we no longer have to download the JS files and host them on our website; the files are now placed in a CDN (Content Delivery Network) which allows us to load these files remotely as quickly as possible.

Let’s review the code:

<style>/* Removes Mobile Highlight */ *{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style>

This line removes the mobile highlight which may appear when you trying to play the game on mobile. (The mobile highlight causes the canvas object to get highlighted and thus ignore your finger movements.)

Next up, we have the loading of the CreateJS libraries:

<script src="http://code.createjs.com/easeljs-0.4.2.min.js"></script>
		<script src="http://code.createjs.com/tweenjs-0.2.0.min.js"></script>
		<script src="http://code.createjs.com/soundjs-0.2.0.min.js"></script>
		<script src="http://code.createjs.com/preloadjs-0.1.0.min.js"></script>
		<script src="http://code.createjs.com/movieclip-0.4.1.min.js"></script>

This code loads the JS files from the CreateJS CDN and it basically allows us to use any of the CreateJS functions in our code

Next, we will load the SoundJS Flash plugin, which provides sound support for browsers that don’t support HTML5 Audio. This is done by using a SWF (a Flash object) to load the sounds.

<script src="assets/soundjs.flashplugin-0.2.0.min.js"></script>

In this case we will not use the CDN; instead, we’ll download the SoundJS library from http://createjs.com/#!/SoundJS/download and place the soundjs.flashplugin-0.2.0.min.js and FlashAudioPlugin.swf files in a local folder named assets.

Last among the JS files, we’ll load the Main.js file which will contain all the code to our game:

<script src="Main.js"></script>

Finally, let’s place a Canvas object on our stage.

<body onload="Main();">
		<canvas id="PongStage" width="480" height="320"></canvas>
	</body>

Now we can start working on the game code.


Step 2: The Variables

Our game code will be inside a file named Main.js, so create and save this now.

First of all, let’s define variables for all the graphic objects in the game:

var canvas; //Will be linked to the canvas in our index.html page
var stage; //Is the equivalent of stage in AS3; we'll add "children" to it

// Graphics
//[Background]

var bg; //The background graphic

//[Title View]

var main; //The Main Background
var startB; //The Start button in the main menu
var creditsB; //The credits button in the main menu

//[Credits]

var credits; //The Credits screen

//[Game View]

var player; //The player paddle graphic
var ball; //The ball graphic
var cpu; //The CPU paddle
var win; //The winning popup
var lose; //The losing popup

I’ve added a comment for each variable so that you’ll know what we’ll be loading in that variable

Next up, the scores:

//[Score]

var playerScore; //The main player score
var cpuScore; //The CPU score
var cpuSpeed=6; //The speed of the CPU paddle; the faster it is the harder the game is

We’ll, need variables for the speed of the ball:

// Variables

var xSpeed = 5;
var ySpeed = 5;

You can change these values to whatever you want, if you’d like to make the game easier or harder.

If you’re a Flash developer, you know that Flash’s onEnterFrame is very useful when creating games, as there are things that need to happen in every given frame. (If you’re not familiar with this idea, check out this article on the Game Loop.)

We have an equivalent for onEnterFrame in CreateJS, and that is the ticker object, which can run code every fraction of a second. Let’s create the variable that will link to it:

var tkr = new Object;

Next we have the preloader, which will use the new PreloadJS methods.

//preloader
var preloader;
var manifest;
var totalLoaded = 0;
  • preloader – will contain the PreloadJS object.
  • manifest – will hold the list of files we need to load.
  • totalLoaded – this variable will hold the number of files already loaded.

Last but not least in our list of variables, we have TitleView, which will hold several graphics within in order to display them together (like a Flash DisplayObjectContainer).

var TitleView = new Container();

Let’s move on to the Main function…


Step 3: The Main() Function

This function is the first function that runs after all the JS files from the index.html are loaded. But what’s calling this function?

Well, remember this line from the index.html file?

<body onload="Main();">

This code snippet states that once the HTML (and JS libraries) are loaded, the Main function should run.

Let’s review it:

function Main()
{
	/* Link Canvas */

	canvas = document.getElementById('PongStage');
  	stage = new Stage(canvas);

  	stage.mouseEventsEnabled = true;

	/* Set The Flash Plugin for browsers that don't support SoundJS */
  	SoundJS.FlashPlugin.BASE_PATH = "assets/";
    if (!SoundJS.checkPlugin(true)) {
      alert("Error!");
      return;
    }

  	manifest = [
				{src:"bg.png", id:"bg"},
				{src:"main.png", id:"main"},
				{src:"startB.png", id:"startB"},
				{src:"creditsB.png", id:"creditsB"},
				{src:"credits.png", id:"credits"},
				{src:"paddle.png", id:"cpu"},
				{src:"paddle.png", id:"player"},
				{src:"ball.png", id:"ball"},
				{src:"win.png", id:"win"},
				{src:"lose.png", id:"lose"},
				{src:"playerScore.ogg", id:"playerScore"},
				{src:"enemyScore.ogg", id:"enemyScore"},
				{src:"hit.ogg", id:"hit"},
				{src:"wall.ogg", id:"wall"}
			];

  	preloader = new PreloadJS();
  	preloader.installPlugin(SoundJS);
    preloader.onProgress = handleProgress;
    preloader.onComplete = handleComplete;
    preloader.onFileLoad = handleFileLoad;
    preloader.loadManifest(manifest);

	/* Ticker */

	Ticker.setFPS(30);
	Ticker.addListener(stage);
}

Let’s break down each part:

  	canvas = document.getElementById('PongStage');
  	stage = new Stage(canvas);

  	stage.mouseEventsEnabled = true;

Here we link the PongStage Canvas object from the index.html file to the canvas variable, and then create a Stage object from that canvas. (The stage will allow us to place objects on it.)

mouseEventsEnabled enables us to use mouse events, so we can detect mouse movements and clicks.

/* Set The Flash Plugin for browsers that don't support SoundJS */
  	SoundJS.FlashPlugin.BASE_PATH = "assets/";
    if (!SoundJS.checkPlugin(true)) {
      alert("Error!");
      return;
    }

Here we configure where the Flash sound plugin resides for those browsers in which HTML5 Audio is not supported

	manifest = [
				{src:"bg.png", id:"bg"},
				{src:"main.png", id:"main"},
				{src:"startB.png", id:"startB"},
				{src:"creditsB.png", id:"creditsB"},
				{src:"credits.png", id:"credits"},
				{src:"paddle.png", id:"cpu"},
				{src:"paddle.png", id:"player"},
				{src:"ball.png", id:"ball"},
				{src:"win.png", id:"win"},
				{src:"lose.png", id:"lose"},
				{src:"playerScore.ogg", id:"playerScore"},
				{src:"enemyScore.ogg", id:"enemyScore"},
				{src:"hit.ogg", id:"hit"},
				{src:"wall.ogg", id:"wall"}
			];

In the manifest variable we place an array of files we want to load (and provide a unique ID for each one

  	preloader = new PreloadJS();
  	preloader.installPlugin(SoundJS);
    preloader.onProgress = handleProgress;
    preloader.onComplete = handleComplete;
    preloader.onFileLoad = handleFileLoad;
    preloader.loadManifest(manifest);

Here we configure the preloader object using PreloadJS. PreloadJS is a new addition to the CreateJS libraries and quite a useful one.

We create a new PreloadJS object and place it in the preloader variable, then assign a method to each event (onProgress, onComplete, onFileLoad). Finally we use the preloader to load the manifest we created earlier.

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

Here we add the Ticker object to the stage and set the frame rate to 30 FPS; we’ll use it later in the game for the enterFrame functionality.


Step 4: Creating the Preloader Functions

function handleProgress(event)
{
	//use event.loaded to get the percentage of the loading
}

function handleComplete(event) {
         //triggered when all loading is complete
}

function handleFileLoad(event) {
         //triggered when an individual file completes loading

         switch(event.type)
         {
         	case PreloadJS.IMAGE:
         	//image loaded
         	 var img = new Image();
              img.src = event.src;
              img.onload = handleLoadComplete;
              window[event.id] = new Bitmap(img);
         	break;

         	case PreloadJS.SOUND:
         	//sound loaded
         	handleLoadComplete();
         	break;
         }
}

Let’s review the functions:

  • handleProgress – In this function you’ll be able to follow the percentage of the loading progress using this parameter: event.loaded. You could use this to create for example a progress bar.
  • handleComplete – This function is called once all the files have been loaded (in case you want to place something there).
  • handleFileLoad – Since we load two types of files – images and sounds – we have this function that will handle each one separately. If it’s an image, we create a bitmap image and place it in a variable (whose name is the same as the ID of the loaded image) and then call the handleLoadComplete function (which we’ll write next); if it’s a sound then we just call the handleLoadComplete immediately.

Now let’s discuss the handleLoadComplete function I just mentioned:

 function handleLoadComplete(event)
 {

	totalLoaded++;

	if(manifest.length==totalLoaded)
	{
		addTitleView();
	}
 }

It’s a pretty straightforward function; we increase the totalLoaded variable (that holds the number of assets loaded so far) and then we check if the number of items in our manifest is the same as the number of loaded assets, and if so, go to the Main Menu screen.


Step 5: Creating the Main Menu

The Main Menu
function addTitleView()
{
	//console.log("Add Title View");
	startB.x = 240 - 31.5;
	startB.y = 160;
	startB.name = 'startB';

	creditsB.x = 241 - 42;
	creditsB.y = 200;

	TitleView.addChild(main, startB, creditsB);
	stage.addChild(bg, TitleView);
	stage.update();

	// Button Listeners

	startB.onPress = tweenTitleView;
	creditsB.onPress = showCredits;

Nothing special here. We place the images of the Background, Start Button and Credits Button on the stage and link onPress event handlers to the Start and Credits buttons.

Here are the functions that display and remove the credits screen and the tweenTitleView which starts the game:

function showCredits()
{
	// Show Credits

	credits.x = 480;

	stage.addChild(credits);
	stage.update();
	Tween.get(credits).to({x:0}, 300);
	credits.onPress = hideCredits;
}

// Hide Credits

function hideCredits(e)
{
	Tween.get(credits).to({x:480}, 300).call(rmvCredits);
}

// Remove Credits

function rmvCredits()
{
	stage.removeChild(credits);
}

// Tween Title View

function tweenTitleView()
{
	// Start Game

	Tween.get(TitleView).to({y:-320}, 300).call(addGameView);
}

Step 6: The Game Code

The PONG game

We’ve reached the main part of this tutorial which is the code of the game itself.

First of all, we need to add all the required assets to the stage, so we do that in the addGameView function:

function addGameView()
{
	// Destroy Menu & Credits screen

	stage.removeChild(TitleView);
	TitleView = null;
	credits = null;

	// Add Game View

	player.x = 2;
	player.y = 160 - 37.5;
	cpu.x = 480 - 25;
	cpu.y = 160 - 37.5;
	ball.x = 240 - 15;
	ball.y = 160 - 15;

	// Score

	playerScore = new Text('0', 'bold 20px Arial', '#A3FF24');
	playerScore.x = 211;
	playerScore.y = 20;

	cpuScore = new Text('0', 'bold 20px Arial', '#A3FF24');
	cpuScore.x = 262;
	cpuScore.y = 20;

	stage.addChild(playerScore, cpuScore, player, cpu, ball);
	stage.update();

	// Start Listener 

	bg.onPress = startGame;
}

Again, a pretty straightforward function that places the objects on the screen and adds a mouseEvent to the background image, so that when the user clicks it the game will start (we will call the startGame function).

Let’s review the startGame function:

function startGame(e)
{
	bg.onPress = null;
	stage.onMouseMove = movePaddle;

	Ticker.addListener(tkr, false);
	tkr.tick = update;
}

Here, as you can see, in addition to adding an onMouseMove event that will move our paddle. We add the tick event, which will call the update function in each frame.

Let’s review the movePaddle and reset functions:

function movePaddle(e)
{
	// Mouse Movement
	player.y = e.stageY;
}

/* Reset */

function reset()
{
	ball.x = 240 - 15;
	ball.y = 160 - 15;
	player.y = 160 - 37.5;
	cpu.y = 160 - 37.5;

	stage.onMouseMove = null;
	Ticker.removeListener(tkr);
	bg.onPress = startGame;
}

In movePaddle, we basically place the user’s paddle at the mouse’s y-coordinate.

In reset, we do something similar to addGameView, except here we don’t add any graphic elements since they are already on the screen.

Using the alert function we’ll display the winning and losing popup:

function alert(e)
{
	Ticker.removeListener(tkr);
	stage.onMouseMove = null;
	bg.onPress = null

	if(e == 'win')
	{
		win.x = 140;
		win.y = -90;

		stage.addChild(win);
		Tween.get(win).to({y: 115}, 300);
	}
	else
	{
		lose.x = 140;
		lose.y = -90;

		stage.addChild(lose);
		Tween.get(lose).to({y: 115}, 300);
	}
}

Step 7: The Game Loop

Now, for the last part of our tutorial we’ll work on the update function (which occurs in every frame of the game – similar to Flash’s onEnterFrame):

function update()
{
	// Ball Movement 

	ball.x = ball.x + xSpeed;
	ball.y = ball.y + ySpeed;

	// Cpu Movement

	if(cpu.y < ball.y) {
		cpu.y = cpu.y + 4;
	}
	else if(cpu.y > ball.y) {
		cpu.y = cpu.y - 4;
	}

	// Wall Collision 

	if((ball.y) < 0) { ySpeed = -ySpeed; SoundJS.play('wall'); };//Up
	if((ball.y + (30)) > 320) { ySpeed = -ySpeed; SoundJS.play('wall');};//down

	/* CPU Score */

	if((ball.x) < 0)
	{
		xSpeed = -xSpeed;
		cpuScore.text = parseInt(cpuScore.text + 1);
		reset();
		SoundJS.play('enemyScore');
	}

	/* Player Score */

	if((ball.x + (30)) > 480)
	{
		xSpeed = -xSpeed;
		playerScore.text = parseInt(playerScore.text + 1);
		reset();
		SoundJS.play('playerScore');
	}

	/* Cpu collision */

	if(ball.x + 30 > cpu.x && ball.x + 30 < cpu.x + 22 && ball.y >= cpu.y && ball.y < cpu.y + 75)
	{
		xSpeed *= -1;
		SoundJS.play('hit');
	}

	/* Player collision */

	if(ball.x <= player.x + 22 && ball.x > player.x && ball.y >= player.y && ball.y < player.y + 75)
	{
		xSpeed *= -1;
		SoundJS.play('hit');
	}

	/* Stop Paddle from going out of canvas */

	if(player.y >= 249)
	{
		player.y = 249;
	}

	/* Check for Win */

	if(playerScore.text == '10')
	{
		alert('win');
	}

	/* Check for Game Over */

	if(cpuScore.text == '10')
	{
		alert('lose');
	}
}

Looks scary, doesn’t it? Don’t worry, we’ll review each part and discuss it.

	// Ball Movement 

	ball.x = ball.x + xSpeed;
	ball.y = ball.y + ySpeed;

In each frame, the ball will move according to its x and y speed values

// Cpu Movement

	if((cpu.y+32) < (ball.y-14)) {
		cpu.y = cpu.y + cpuSpeed;
	}
	else if((cpu.y+32) > (ball.y+14)) {
		cpu.y = cpu.y - cpuSpeed;
	}

Here we have the basic AI of the computer, in which the computer’s paddle simply follows the ball without any special logic. We just compare the location of the center of the paddle (which is why we add 32 pixels to the cpu Y value) to the location of the ball, with a small offset, and move the paddle up or down as necessary.

if((ball.y) < 0) { //top
	ySpeed = -ySpeed;
	SoundJS.play('wall');
};
if((ball.y + (30)) > 320) { //bottom
	ySpeed = -ySpeed;
	SoundJS.play('wall');
};

If the ball hits the top border or the bottom border of the screen, the ball changes direction and we play the Wall Hit sound.

 	/* CPU Score */
 	if((ball.x) < 0)
 	{
 		xSpeed = -xSpeed;
 		cpuScore.text = parseInt(cpuScore.text + 1);
 		reset();
 		SoundJS.play('enemyScore');
 	}
 	/* Player Score */
  	if((ball.x + (30)) > 480)
 	{
 		xSpeed = -xSpeed;
 		playerScore.text = parseInt(playerScore.text + 1);
 		reset();
 		SoundJS.play('playerScore');
 	}

The score login is simple: if the ball passes the left or right borders it increases the score of the player or CPU respectively, plays a sound, and resets the location of the objects using the reset function we’ve discussed earlier.

/* CPU collision */
if(ball.x + 30 > cpu.x && ball.x + 30 < cpu.x + 22 && ball.y >= cpu.y && ball.y < cpu.y + 75)
{
	xSpeed *= -1;
	SoundJS.play('hit');
}
/* Player collision */
if(ball.x <= player.x + 22 && ball.x > player.x && ball.y >= player.y && ball.y < player.y + 75)
{
 	xSpeed *= -1;
 	SoundJS.play('hit');
 }

Here we deal with collisions of the ball with the paddles; every time the ball hits one of the paddles, the ball changes direction and a sound is played

 	if(player.y >= 249)
 	{
 		player.y = 249;
 	}

If the player’s paddle goes out of bounds, we place it back within the bounds.

 /* Check for Win */
 if(playerScore.text == '10')
 {
 	alert('win');
}
/* Check for Game Over */
if(cpuScore.text == '10')
{
 	alert('lose');
}

In this snippet, we check whether either of the players’ score has reached 10 points, and if so we display the winning or losing popup to the player (according to his winning status).


Conclusion

That’s it, you’ve created an entire pong game using CreateJS. Thank you for taking the time to read this tutorial.



View full post on Activetuts+

banner ad

10 Responses to “Learn CreateJS by Building an HTML5 Pong Game”

  1. Daniel Albu says:
    June 26, 2012 at 9:38 pm

    The web moves fast – so fast that our original EaselJS tutorial is already out of date! In this tutorial, you’ll learn how to use the newest CreateJS suite by creating a simple Pong clone.


    Final Result Preview

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

    The PONG game

    Click to play

    This tutorial is based on Carlos Yanez’s Create a Pong Game in HTML5 With EaselJS, which in turn built on his Getting Started With EaselJS guide. The graphics and sound effects are all taken from the former tutorial.


    Step 1: Create index.html

    This will be our main index.html file:

    
    
    <!DOCTYPE html>
    <html>
    	<head>
    		<title>Pong</title>
    
    		<style>/* Removes Mobile Highlight */ *{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style>
    
    		<script src="http://code.createjs.com/easeljs-0.4.2.min.js"></script&gt;
    		<script src="http://code.createjs.com/tweenjs-0.2.0.min.js"></script&gt;
    		<script src="http://code.createjs.com/soundjs-0.2.0.min.js"></script&gt;
    		<script src="http://code.createjs.com/preloadjs-0.1.0.min.js"></script&gt;
    		<script src="http://code.createjs.com/movieclip-0.4.1.min.js"></script&gt;
    		<script src="assets/soundjs.flashplugin-0.2.0.min.js"></script>
    		<script src="Main.js"></script>
    
    	</head>
    	<body onload="Main();">
    		<canvas id="PongStage" width="480" height="320"></canvas>
    	</body>
    </html>
    

    As you can see, it’s pretty short and consists mainly of loading the CreateJS libraries.

    Since the release of CreateJS (which basically bundles all the separate EaselJS libraries) we no longer have to download the JS files and host them on our website; the files are now placed in a CDN (Content Delivery Network) which allows us to load these files remotely as quickly as possible.

    Let’s review the code:

    
    
    <style>/* Removes Mobile Highlight */ *{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style>

    This line removes the mobile highlight which may appear when you trying to play the game on mobile. (The mobile highlight causes the canvas object to get highlighted and thus ignore your finger movements.)

    Next up, we have the loading of the CreateJS libraries:

    
    
    <script src="http://code.createjs.com/easeljs-0.4.2.min.js"></script&gt;
    		<script src="http://code.createjs.com/tweenjs-0.2.0.min.js"></script&gt;
    		<script src="http://code.createjs.com/soundjs-0.2.0.min.js"></script&gt;
    		<script src="http://code.createjs.com/preloadjs-0.1.0.min.js"></script&gt;
    		<script src="http://code.createjs.com/movieclip-0.4.1.min.js"></script&gt;
    

    This code loads the JS files from the CreateJS CDN and it basically allows us to use any of the CreateJS functions in our code

    Next, we will load the SoundJS Flash plugin, which provides sound support for browsers that don’t support HTML5 Audio. This is done by using a SWF (a Flash object) to load the sounds.

    
    
    <script src="assets/soundjs.flashplugin-0.2.0.min.js"></script>
    

    In this case we will not use the CDN; instead, we’ll download the SoundJS library from http://createjs.com/#!/SoundJS/download and place the soundjs.flashplugin-0.2.0.min.js and FlashAudioPlugin.swf files in a local folder named assets.

    Last among the JS files, we’ll load the Main.js file which will contain all the code to our game:

    
    
    <script src="Main.js"></script>
    

    Finally, let’s place a Canvas object on our stage.

    
    
    <body onload="Main();">
    		<canvas id="PongStage" width="480" height="320"></canvas>
    	</body>
    

    Now we can start working on the game code.


    Step 2: The Variables

    Our game code will be inside a file named Main.js, so create and save this now.

    First of all, let’s define variables for all the graphic objects in the game:

    
    
    var canvas; //Will be linked to the canvas in our index.html page
    var stage; //Is the equivalent of stage in AS3; we'll add "children" to it
    
    // Graphics
    //[Background]
    
    var bg; //The background graphic
    
    //[Title View]
    
    var main; //The Main Background
    var startB; //The Start button in the main menu
    var creditsB; //The credits button in the main menu
    
    //[Credits]
    
    var credits; //The Credits screen
    
    //[Game View]
    
    var player; //The player paddle graphic
    var ball; //The ball graphic
    var cpu; //The CPU paddle
    var win; //The winning popup
    var lose; //The losing popup
    

    I’ve added a comment for each variable so that you’ll know what we’ll be loading in that variable

    Next up, the scores:

    
    
    //[Score]
    
    var playerScore; //The main player score
    var cpuScore; //The CPU score
    var cpuSpeed=6; //The speed of the CPU paddle; the faster it is the harder the game is
    

    We’ll, need variables for the speed of the ball:

    
    
    // Variables
    
    var xSpeed = 5;
    var ySpeed = 5;
    

    You can change these values to whatever you want, if you’d like to make the game easier or harder.

    If you’re a Flash developer, you know that Flash’s onEnterFrame is very useful when creating games, as there are things that need to happen in every given frame. (If you’re not familiar with this idea, check out this article on the Game Loop.)

    We have an equivalent for onEnterFrame in CreateJS, and that is the ticker object, which can run code every fraction of a second. Let’s create the variable that will link to it:

    
    
    var tkr = new Object;
    

    Next we have the preloader, which will use the new PreloadJS methods.

    
    
    //preloader
    var preloader;
    var manifest;
    var totalLoaded = 0;
    
    • preloader – will contain the PreloadJS object.
    • manifest – will hold the list of files we need to load.
    • totalLoaded – this variable will hold the number of files already loaded.

    Last but not least in our list of variables, we have TitleView, which will hold several graphics within in order to display them together (like a Flash DisplayObjectContainer).

    
    
    var TitleView = new Container();
    

    Let’s move on to the Main function…


    Step 3: The Main() Function

    This function is the first function that runs after all the JS files from the index.html are loaded. But what’s calling this function?

    Well, remember this line from the index.html file?

    
    
    <body onload="Main();">
    

    This code snippet states that once the HTML (and JS libraries) are loaded, the Main function should run.

    Let’s review it:

    
    
    function Main()
    {
    	/* Link Canvas */
    
    	canvas = document.getElementById('PongStage');
      	stage = new Stage(canvas);
    
      	stage.mouseEventsEnabled = true;
    
    	/* Set The Flash Plugin for browsers that don't support SoundJS */
      	SoundJS.FlashPlugin.BASE_PATH = "assets/";
        if (!SoundJS.checkPlugin(true)) {
          alert("Error!");
          return;
        }
    
      	manifest = [
    				{src:"bg.png", id:"bg"},
    				{src:"main.png", id:"main"},
    				{src:"startB.png", id:"startB"},
    				{src:"creditsB.png", id:"creditsB"},
    				{src:"credits.png", id:"credits"},
    				{src:"paddle.png", id:"cpu"},
    				{src:"paddle.png", id:"player"},
    				{src:"ball.png", id:"ball"},
    				{src:"win.png", id:"win"},
    				{src:"lose.png", id:"lose"},
    				{src:"playerScore.ogg", id:"playerScore"},
    				{src:"enemyScore.ogg", id:"enemyScore"},
    				{src:"hit.ogg", id:"hit"},
    				{src:"wall.ogg", id:"wall"}
    			];
    
      	preloader = new PreloadJS();
      	preloader.installPlugin(SoundJS);
        preloader.onProgress = handleProgress;
        preloader.onComplete = handleComplete;
        preloader.onFileLoad = handleFileLoad;
        preloader.loadManifest(manifest);
    
    	/* Ticker */
    
    	Ticker.setFPS(30);
    	Ticker.addListener(stage);
    }
    

    Let’s break down each part:

    
    
      	canvas = document.getElementById('PongStage');
      	stage = new Stage(canvas);
    
      	stage.mouseEventsEnabled = true;
    

    Here we link the PongStage Canvas object from the index.html file to the canvas variable, and then create a Stage object from that canvas. (The stage will allow us to place objects on it.)

    mouseEventsEnabled enables us to use mouse events, so we can detect mouse movements and clicks.

    
    
    /* Set The Flash Plugin for browsers that don't support SoundJS */
      	SoundJS.FlashPlugin.BASE_PATH = "assets/";
        if (!SoundJS.checkPlugin(true)) {
          alert("Error!");
          return;
        }
    

    Here we configure where the Flash sound plugin resides for those browsers in which HTML5 Audio is not supported

    
    
    	manifest = [
    				{src:"bg.png", id:"bg"},
    				{src:"main.png", id:"main"},
    				{src:"startB.png", id:"startB"},
    				{src:"creditsB.png", id:"creditsB"},
    				{src:"credits.png", id:"credits"},
    				{src:"paddle.png", id:"cpu"},
    				{src:"paddle.png", id:"player"},
    				{src:"ball.png", id:"ball"},
    				{src:"win.png", id:"win"},
    				{src:"lose.png", id:"lose"},
    				{src:"playerScore.ogg", id:"playerScore"},
    				{src:"enemyScore.ogg", id:"enemyScore"},
    				{src:"hit.ogg", id:"hit"},
    				{src:"wall.ogg", id:"wall"}
    			];
    

    In the manifest variable we place an array of files we want to load (and provide a unique ID for each one

    
    
      	preloader = new PreloadJS();
      	preloader.installPlugin(SoundJS);
        preloader.onProgress = handleProgress;
        preloader.onComplete = handleComplete;
        preloader.onFileLoad = handleFileLoad;
        preloader.loadManifest(manifest);
    

    Here we configure the preloader object using PreloadJS. PreloadJS is a new addition to the CreateJS libraries and quite a useful one.

    We create a new PreloadJS object and place it in the preloader variable, then assign a method to each event (onProgress, onComplete, onFileLoad). Finally we use the preloader to load the manifest we created earlier.

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

    Here we add the Ticker object to the stage and set the frame rate to 30 FPS; we’ll use it later in the game for the enterFrame functionality.


    Step 4: Creating the Preloader Functions

    
    
    function handleProgress(event)
    {
    	//use event.loaded to get the percentage of the loading
    }
    
    function handleComplete(event) {
             //triggered when all loading is complete
    }
    
    function handleFileLoad(event) {
             //triggered when an individual file completes loading
    
             switch(event.type)
             {
             	case PreloadJS.IMAGE:
             	//image loaded
             	 var img = new Image();
                  img.src = event.src;
                  img.onload = handleLoadComplete;
                  window[event.id] = new Bitmap(img);
             	break;
    
             	case PreloadJS.SOUND:
             	//sound loaded
             	handleLoadComplete();
             	break;
             }
    }
    

    Let’s review the functions:

    • handleProgress – In this function you’ll be able to follow the percentage of the loading progress using this parameter: event.loaded. You could use this to create for example a progress bar.
    • handleComplete – This function is called once all the files have been loaded (in case you want to place something there).
    • handleFileLoad – Since we load two types of files – images and sounds – we have this function that will handle each one separately. If it’s an image, we create a bitmap image and place it in a variable (whose name is the same as the ID of the loaded image) and then call the handleLoadComplete function (which we’ll write next); if it’s a sound then we just call the handleLoadComplete immediately.

    Now let’s discuss the handleLoadComplete function I just mentioned:

    
    
     function handleLoadComplete(event)
     {
    
    	totalLoaded++;
    
    	if(manifest.length==totalLoaded)
    	{
    		addTitleView();
    	}
     }
    

    It’s a pretty straightforward function; we increase the totalLoaded variable (that holds the number of assets loaded so far) and then we check if the number of items in our manifest is the same as the number of loaded assets, and if so, go to the Main Menu screen.


    Step 5: Creating the Main Menu

    The Main Menu
    
    
    function addTitleView()
    {
    	//console.log("Add Title View");
    	startB.x = 240 - 31.5;
    	startB.y = 160;
    	startB.name = 'startB';
    
    	creditsB.x = 241 - 42;
    	creditsB.y = 200;
    
    	TitleView.addChild(main, startB, creditsB);
    	stage.addChild(bg, TitleView);
    	stage.update();
    
    	// Button Listeners
    
    	startB.onPress = tweenTitleView;
    	creditsB.onPress = showCredits;
    

    Nothing special here. We place the images of the Background, Start Button and Credits Button on the stage and link onPress event handlers to the Start and Credits buttons.

    Here are the functions that display and remove the credits screen and the tweenTitleView which starts the game:

    
    
    function showCredits()
    {
    	// Show Credits
    
    	credits.x = 480;
    
    	stage.addChild(credits);
    	stage.update();
    	Tween.get(credits).to({x:0}, 300);
    	credits.onPress = hideCredits;
    }
    
    // Hide Credits
    
    function hideCredits(e)
    {
    	Tween.get(credits).to({x:480}, 300).call(rmvCredits);
    }
    
    // Remove Credits
    
    function rmvCredits()
    {
    	stage.removeChild(credits);
    }
    
    // Tween Title View
    
    function tweenTitleView()
    {
    	// Start Game
    
    	Tween.get(TitleView).to({y:-320}, 300).call(addGameView);
    }
    

    Step 6: The Game Code

    The PONG game

    We’ve reached the main part of this tutorial which is the code of the game itself.

    First of all, we need to add all the required assets to the stage, so we do that in the addGameView function:

    
    
    function addGameView()
    {
    	// Destroy Menu & Credits screen
    
    	stage.removeChild(TitleView);
    	TitleView = null;
    	credits = null;
    
    	// Add Game View
    
    	player.x = 2;
    	player.y = 160 - 37.5;
    	cpu.x = 480 - 25;
    	cpu.y = 160 - 37.5;
    	ball.x = 240 - 15;
    	ball.y = 160 - 15;
    
    	// Score
    
    	playerScore = new Text('0', 'bold 20px Arial', '#A3FF24');
    	playerScore.x = 211;
    	playerScore.y = 20;
    
    	cpuScore = new Text('0', 'bold 20px Arial', '#A3FF24');
    	cpuScore.x = 262;
    	cpuScore.y = 20;
    
    	stage.addChild(playerScore, cpuScore, player, cpu, ball);
    	stage.update();
    
    	// Start Listener 
    
    	bg.onPress = startGame;
    }
    

    Again, a pretty straightforward function that places the objects on the screen and adds a mouseEvent to the background image, so that when the user clicks it the game will start (we will call the startGame function).

    Let’s review the startGame function:

    
    
    function startGame(e)
    {
    	bg.onPress = null;
    	stage.onMouseMove = movePaddle;
    
    	Ticker.addListener(tkr, false);
    	tkr.tick = update;
    }
    

    Here, as you can see, in addition to adding an onMouseMove event that will move our paddle. We add the tick event, which will call the update function in each frame.

    Let’s review the movePaddle and reset functions:

    
    
    function movePaddle(e)
    {
    	// Mouse Movement
    	player.y = e.stageY;
    }
    
    /* Reset */
    
    function reset()
    {
    	ball.x = 240 - 15;
    	ball.y = 160 - 15;
    	player.y = 160 - 37.5;
    	cpu.y = 160 - 37.5;
    
    	stage.onMouseMove = null;
    	Ticker.removeListener(tkr);
    	bg.onPress = startGame;
    }
    

    In movePaddle, we basically place the user’s paddle at the mouse’s y-coordinate.

    In reset, we do something similar to addGameView, except here we don’t add any graphic elements since they are already on the screen.

    Using the alert function we’ll display the winning and losing popup:

    
    
    function alert(e)
    {
    	Ticker.removeListener(tkr);
    	stage.onMouseMove = null;
    	bg.onPress = null
    
    	if(e == 'win')
    	{
    		win.x = 140;
    		win.y = -90;
    
    		stage.addChild(win);
    		Tween.get(win).to({y: 115}, 300);
    	}
    	else
    	{
    		lose.x = 140;
    		lose.y = -90;
    
    		stage.addChild(lose);
    		Tween.get(lose).to({y: 115}, 300);
    	}
    }
    

    Step 7: The Game Loop

    Now, for the last part of our tutorial we’ll work on the update function (which occurs in every frame of the game – similar to Flash’s onEnterFrame):

    
    
    function update()
    {
    	// Ball Movement 
    
    	ball.x = ball.x + xSpeed;
    	ball.y = ball.y + ySpeed;
    
    	// Cpu Movement
    
    	if(cpu.y < ball.y) {
    		cpu.y = cpu.y + 4;
    	}
    	else if(cpu.y > ball.y) {
    		cpu.y = cpu.y - 4;
    	}
    
    	// Wall Collision 
    
    	if((ball.y) < 0) { ySpeed = -ySpeed; SoundJS.play('wall'); };//Up
    	if((ball.y + (30)) > 320) { ySpeed = -ySpeed; SoundJS.play('wall');};//down
    
    	/* CPU Score */
    
    	if((ball.x) < 0)
    	{
    		xSpeed = -xSpeed;
    		cpuScore.text = parseInt(cpuScore.text + 1);
    		reset();
    		SoundJS.play('enemyScore');
    	}
    
    	/* Player Score */
    
    	if((ball.x + (30)) > 480)
    	{
    		xSpeed = -xSpeed;
    		playerScore.text = parseInt(playerScore.text + 1);
    		reset();
    		SoundJS.play('playerScore');
    	}
    
    	/* Cpu collision */
    
    	if(ball.x + 30 > cpu.x && ball.x + 30 < cpu.x + 22 && ball.y >= cpu.y && ball.y < cpu.y + 75)
    	{
    		xSpeed *= -1;
    		SoundJS.play('hit');
    	}
    
    	/* Player collision */
    
    	if(ball.x <= player.x + 22 && ball.x > player.x && ball.y >= player.y && ball.y < player.y + 75)
    	{
    		xSpeed *= -1;
    		SoundJS.play('hit');
    	}
    
    	/* Stop Paddle from going out of canvas */
    
    	if(player.y >= 249)
    	{
    		player.y = 249;
    	}
    
    	/* Check for Win */
    
    	if(playerScore.text == '10')
    	{
    		alert('win');
    	}
    
    	/* Check for Game Over */
    
    	if(cpuScore.text == '10')
    	{
    		alert('lose');
    	}
    }
    

    Looks scary, doesn’t it? Don’t worry, we’ll review each part and discuss it.

    
    
    	// Ball Movement 
    
    	ball.x = ball.x + xSpeed;
    	ball.y = ball.y + ySpeed;
    

    In each frame, the ball will move according to its x and y speed values

    
    
    // Cpu Movement
    
    	if((cpu.y+32) < (ball.y-14)) {
    		cpu.y = cpu.y + cpuSpeed;
    	}
    	else if((cpu.y+32) > (ball.y+14)) {
    		cpu.y = cpu.y - cpuSpeed;
    	}
    

    Here we have the basic AI of the computer, in which the computer’s paddle simply follows the ball without any special logic. We just compare the location of the center of the paddle (which is why we add 32 pixels to the cpu Y value) to the location of the ball, with a small offset, and move the paddle up or down as necessary.

    
    
    if((ball.y) < 0) { //top
    	ySpeed = -ySpeed;
    	SoundJS.play('wall');
    };
    if((ball.y + (30)) > 320) { //bottom
    	ySpeed = -ySpeed;
    	SoundJS.play('wall');
    };
    

    If the ball hits the top border or the bottom border of the screen, the ball changes direction and we play the Wall Hit sound.

    
    
     	/* CPU Score */
     	if((ball.x) < 0)
     	{
     		xSpeed = -xSpeed;
     		cpuScore.text = parseInt(cpuScore.text + 1);
     		reset();
     		SoundJS.play('enemyScore');
     	}
     	/* Player Score */
      	if((ball.x + (30)) > 480)
     	{
     		xSpeed = -xSpeed;
     		playerScore.text = parseInt(playerScore.text + 1);
     		reset();
     		SoundJS.play('playerScore');
     	}
    

    The score login is simple: if the ball passes the left or right borders it increases the score of the player or CPU respectively, plays a sound, and resets the location of the objects using the reset function we’ve discussed earlier.

    
    
    /* CPU collision */
    if(ball.x + 30 > cpu.x && ball.x + 30 < cpu.x + 22 && ball.y >= cpu.y && ball.y < cpu.y + 75)
    {
    	xSpeed *= -1;
    	SoundJS.play('hit');
    }
    /* Player collision */
    if(ball.x <= player.x + 22 && ball.x > player.x && ball.y >= player.y && ball.y < player.y + 75)
    {
     	xSpeed *= -1;
     	SoundJS.play('hit');
     }
    

    Here we deal with collisions of the ball with the paddles; every time the ball hits one of the paddles, the ball changes direction and a sound is played

    
    
     	if(player.y >= 249)
     	{
     		player.y = 249;
     	}
    

    If the player’s paddle goes out of bounds, we place it back within the bounds.

    
    
     /* Check for Win */
     if(playerScore.text == '10')
     {
     	alert('win');
    }
    /* Check for Game Over */
    if(cpuScore.text == '10')
    {
     	alert('lose');
    }
    

    In this snippet, we check whether either of the players’ score has reached 10 points, and if so we display the winning or losing popup to the player (according to his winning status).


    Conclusion

    That’s it, you’ve created an entire pong game using CreateJS. Thank you for taking the time to read this tutorial.


  2. Sebastian Bratu says:
    June 26, 2012 at 10:00 pm

    In this mini-series, exclusive to Tuts+ Premium members, you’ll learn how to use Flash to build a Facebook Graph API application that can create slideshows for your public pages. The final part shows you how to actually retrieve and display the information from Facebook.


    Premium Preview

    Click to try the app on Facebook.

    This application allows you to select a Facebook album or event list from one of your public pages and turn it into a slideshow for your page tab. When the users enter your page, they will see photos from your chosen album, with your photo title and description, or event name, date and invites (for the event tab).

    In the previous part of this series, we created the event slider generator. In this part we’ll make the actual slider for the images (and later, for the events).

    You’ll need to be logged in to Facebook in order to see this demo: https://apps.facebook.com/activetuts_tabmaker/


    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 for free.


    Tuts+ Premium Membership

    We run a Premium membership system which periodically gives members access to extra tutorials, like this one, from across the whole Tuts+ network. If you’re a Premium member, you can log in and read 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.


  3. Porter says:
    June 26, 2012 at 10:12 pm

    Earlier today, Wilson Lim showed you how to create a gravity-based game called Flux. In this Workshop, Matt Porter critiques Flux, explaining what it would take to turn that simple demo into a real game.


    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.

    Please bear in mind that this demo was created specifically for a tutorial, rather than for release on a Flash portal, so it’s naturally less polished than games we’ve featured in past critiques.


    Introduction

    Flux is a barebones game. It has one core mechanic, and very basic controls. That being said, even the most basic aspects of a game can require careful balance. With a few small tweaks, we can make something that’s simple and frustrating into something that might not necessarily be a blast, but will be a much smoother and more enjoyable experience.

    The core aim of Flux is to sustain energy for your ship by collecting white crystals, while at the same time avoiding red crystals. In addition, you must also avoid rocks, which end your game immediately upon contact. To mix things up a bit, the ship is equipped with a magnet of sorts, that can attract or deflect the negative crystals, but has no effect on the rocks of instant doom.

    You can move your ship horizontally, but not vertically, using the left and right arrow keys. The last bit of spice in this otherwise currently bland game is that you can increase or decrease your magnet’s area of effect, by pressing the up and down arrow keys respectively.

    So there you have it, that’s Flux. While there’s very little to this game, we’re about to break it down into more than the average eyes see, and come up with some simple, yet game changing, alterations.


    Getting Started

    The first and most immediate flaw in Flux is that there isn’t really a title screen.

    Flux’s starting screen

    There’s no instructions, no place to check high score, no title, no music… you’re just tossed onto a bland screen with a Start Game button. Pretty bad start, but okay, let’s move on.

    Upon pressing the button, we now see our ship, and some objects in our face. Let’s just assume that we know what to do right off, and that there is a rock (instant death if it hits us) coming right at us (that’ll happen when positions are 100% random). We quickly get our hands onto the keyboard (we started using the mouse, and there were no instructions, so we’re not actually prepared for this), and attempt to dodge the rock.

    Oh no, our ship isn’t moving! Does WASD not work? Well, actually, they don’t work (which is a horrible decision, as WASD and arrow keys should always both be supported where possible) – but believe it or not, that’s not our issue either.

    The real issue is that the game area doesn’t have focus. We actually need to click the player area to gain control, even though we just pressed the Start Game button. Looks like we just blew up from an oncoming rock. So here we are, literally five seconds into the game, and all we’ve done is see a bland title screen and die from absolute unfairness. Congratulations, you’ve just lost the majority of all your players right off, and most of them have down-voted your game if it’s being played on a major portal such as Newgrounds or Kongregate.

    A likely response from a Newgrounds gamer

    While the above is an absolute mess, it’s actually quite easily fixed.

    Pixel Purge‘s title screen, for comparison

    First off, we add a simple title screen. The quality can range greatly, but at the very least, we need a title, a play button, and something related to scores – whether it’s a list already on screen, or a button to let us view them all.

    Next, we make sure that the play area has keyboard focus after the Start Game button is pressed. If this were my game, I would then choose to display the controls of the game to the player through pictures and text, and not just a wall of text. For good measure, I’d save a variable to a shared object that says the player has seen the controls, and I would never display them at the start of a game again (unless a “delete all data” button was pressed).

    Now that the player has a good initial first impression, with a decent menu, and controls shown to them, we’d start the game. Here I would make sure that the game didn’t actually start until the player moved the ship. This would accomplish two things: first, we’d know that they have their hands on the keyboard and are ready to play; and second, they wouldn’t die from a randomly generated flying space rock within the first two seconds of the game.

    Nothing that I just listed above is hard, but it’s just changed that poor initial first impression of this game to “this has potential, let’s see what happens”.


    Gameplay

    Now that we’ve taken care of analyzing the first impression, let’s focus a bit on the actual gameplay.

    Flux’s play screen

    The first thing I noticed when playing Flux, is that the movement was extremely stiff, and felt very amateur. It’s obvious that the movement is locked to a set speed, and that there’s no acceleration or easing. If we were to add some of that then not only would the game feel better and look more smooth, but our control would be far more precise, making for a much more enjoyable experience.

    The magnet mechanic is actually pretty neat, but it’s a bit rough around the edges. The first thing I noticed, is that there are no restrictions on how big or small the attract radius can be. This allows us to go negative, and eventually appear to be positive again, but the magnet won’t actually do anything. This could leave various impressions on the player, from them being confused to them thinking the game looks unprofessional, so it’s important that we put restrictions in place.


    One More Time

    Assuming that players actually have fun with the game the way it is (admittedly doubtful beyond the first play or two), we still have some fixing up to do. When the player dies, they aren’t really left with any incentive to play again. The game over screen should be used as an opportunity to tempt the player to play again – and simply having a button to let them do so is not what I mean.

    Flux’s game over screen

    In this case, the game over screen should still show the player’s score, but also their all-time best score. If their previous play was their best, this should be related to the player both visually and audibly.

    Pixel Purge’s game over screen, for comparison

    If we wanted to take things even further, we’d toss in Facebook / Twitter buttons, and allow the player to brag about their accomplishment with friends.


    What Else?

    As I’ve mentioned, even with the critical flaws fixed, and the controls a bit polished, the game is still a bit boring. While there are hundreds if not thousands of directions in which to take a game this basic, I’ll just focus on some of the simpler yet still effective changes.

    The first addition I would add is powerups. We’ve already got collision code we use for collecting crystals, so adding powerups is not that hard from a technical standpoint. For example, we could add a powerup that turns every red crystal into a white one. With a cool visual effect, and an awesome sound effect, grabbing one of these would be quite rewarding.

    The next thing I would do, is add crystals of different sizes, where the bigger the crystal, the harder it is to attract or repel. Give the larger crystals a higher score value, and a more rewarding sound, and you’ve now got some substance to your game. You’ll find players act extra risky around instant-kill death rocks, just so they can attempt to pull in a giant white crystal.

    Speaking of instant-kill death rocks, why not add a way to get rid of them? With the simple press of a button (say, the X key), let the player shoot directly ahead – for a cost. To make the game more interesting, firing your weapon would require some of your energy, so it would have to be used sparingly. We could also add a powerup that explodes all rocks on the screen, or that makes the player invincible so that they can hit them without worry for a limited time.

    If I really wanted to add a level of complexity to the game, I’d make it so that all crystals gained would be stored as currency, and after each game (or level), the player could spend those points on upgrading stats. These stats could range from maximum magnet radius, to increased energy regeneration from white crystals; the possibilities are nearly endless.

    All of the biggest remaining issues are related to polish, and as many developers will tell you, this can take a long time to get right.

    Some of the more major aspects of polish that are needed are as follows:

    • The Times New Roman font needs to be replaced.
    • The game needs consistent audio toggle buttons (to be found on all screens).
    • More visual effects are needed to increase the graphical quality.
    • The game needs to be 100% audio complete, with both sounds and music.

    Conclusion

    As you can see, it didn’t take too much to really rip this game apart, and then point out some simple but effective ways to fix it up.

    There are enormous benefits to being able to fix up such a basic game. In reality, everything that Flux has is no larger or more complex than one individual portion of any other larger game. If we look at game development like this, we then see the benefit of being able to fix up such a simple game. We’re essentially able to view our bigger projects as small pieces, and we can then polish each piece up individually until it’s a smooth and enjoyable experience on its own. In the end, we’ll be left with a full-fledged game, comprised of many small, extremely well built pieces.

    What do you think should be added to Flux? Post your suggestions in the comments – or you could even follow the tutorial and make the changes yourself…


  4. Wilson Lim says:
    June 26, 2012 at 10:57 pm

    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 – take a look at this critique for tips on how you can take it from a simple demo to a full game!


    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);
    
    				rSpeed = speed;
    			}
    
    			// we will call this every frame
    			public function move():void
    			{
    				this.y += rSpeed;
    				//rotation speed is linked to moving speed
    				this.rotation += rSpeed / 8;
    			}
    		}
    	}
    

    Step 3: The GameScreen Class

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

    Create the class:

    
    
    package
    {
    
    	public class GameScreen extends MovieClip
    	{
    
    		public function GameScreen()
    		{
    
    		}
    	}
    }
    

    That’s all we need for now.


    Step 4: Update The Main Class

    We’ll now create an instance of GameScreen within Main:

    
    
    package
    {
    	import flash.display.Sprite;
    	import flash.events.Event;
    
    	[SWF(width = "550", height = "600")]
    
    	public class Main extends Sprite
    	{
    		private var game:GameScreen;
    
    		public function Main():void
    		{
    			// don't display a yellow rectangle on the screen at startup
    			stage.stageFocusRect = false;
    
    			game = new GameScreen();
    			addChild(game);
    
    			// give keyboard focus to the game screen immediately
    			stage.focus = game;
    		}
    	}
    }
    

    Why bother? Well, this way, it’ll be easier to add extra screens later if we want to (like a preloader, a title screen, a game over screen…).


    Step 5: Introducing a Manager Class

    To avoid the GameScreen 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
    	{
    		// this Vector will store all instances of the Energy class
    		private var energyList:Vector.<Energy>
    		private var gameScreen:GameScreen;
    
    		public function EnergyManager(gs:GameScreen)
    		{
    			gameScreen = gs;
    			energyList = new Vector.<Energy>;
    		}
    	}
    }
    

    Note that we require a reference to the GameScreen to be passed to the constructor, and we store this reference in a private variable. We also set up a Vector to store references to all the energy objects.

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


    Step 6: Creating Energy

    Add the below function for creating energy, this is just a function; we will call the function later from GameScreen Class:

    
    
    	public function createEnergy(number:int):void
    	{
    		var energy:Energy;
    		for (var i:int = 0; i < number; i++) {		
    
    			energy = new Energy(4);				
    
    			gameScreen.addEnergyToScreen(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 to the display list (via the GameScreen), add it to the Vector of all energy objects that we just created, and set its position to a random point within certain bounds.

    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.

    Now, what’s that addEnergyToScreen() function? We haven’t defined that yet, so let’s do it now. Add this to GameScreen:

    
    
    		public function addEnergyToScreen(energy:Energy):void
    		{
    			addChild(energy);
    		}
    

    It just adds the passed instance of energy to the display list. Let’s also make a corresponding function to remove a given energy object from the screen:

    
    
    		public function removeEnergyFromScreen(energy:Energy):void
    		{
    			if (energy.parent == this)
    			{
    				removeChild(energy);
    			}
    		}
    

    Step 7: Spawning Energy

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

    
    
    energyM = new EnergyManager(this);	//remember to pass a reference to the game screen
    
    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 GameScreen to add the player to the screen:

    
    
    // in the variable definitions
    public var player:Player;
    
    
    
    // in the constructor function
    player = new Player;
    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:
      
      
      		addEventListener(Event.ENTER_FRAME, update);
      		addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler);
      		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 (isGravityPushing == true) {
      				isGravityPushing = false;
      			} else  {
      				isGravityPushing = 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.events.Event;
        import flash.events.TimerEvent;
        import flash.ui.Keyboard;
        import flash.utils.Timer;
        import flash.events.KeyboardEvent;
    
        public class GameScreen
        {
            public var player:Player;
    
            private var energyM:EnergyManager;
    
            private var moveRight:Boolean = false;
            private var moveLeft:Boolean = false;
            private var isGravityPushing:Boolean = true;
    
            private var returnedPower:int = 0;
    
            private var scoreText:Text;
            private var totalScore:int=0;
            private var score:Text;
    
            public function GameScreen()
            {
                scoreText = new Text("Score :");
                addChild(scoreText);
    
                energyM = new EnergyManager;
    
                var spawnTimer:Timer = new Timer(3000, 0);
                spawnTimer.addEventListener(TimerEvent.TIMER, spawnEnergy);
                spawnTimer.start();
    
                player = new Player;
                addChild(player);
                player.x = 275;
                player.y = 450;
    
                addEventListener(Event.ENTER_FRAME, update);
                addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler);
                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 (isGravityPushing == true) {
    				isGravityPushing = false;
    			}else if (isGravityPushing == false) {
    				isGravityPushing = 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: Move the Energy Supplies

    At the moment, the energy supplies are spawning but not moving. We’ll use the GameScreen.update() function to make them move, since it runs every frame.

    Add this code to GameScreen.update():

    
    
    			energyM.moveAll();  // will make every energy object move
    

    Now of course we need to make the EnergyManager.moveAll() function, so add this to EnergyManager.as:

    
    
    		public function moveAll():void
    		{
    			for (var i:int = 0; i < energyList.length; i++) {
    				var energyS:Energy = energyList[i];
    				energyS.move();
    			}
    		}
    

    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 GameScreen.

    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) {
    				gameScreen.removeEnergyFromScreen(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 Pythagoras.
    • 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 GameScreen.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 Pythagoras’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 Pythagoras.
    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 GameScreen – but before that, we will need to use a Boolean function to toggle between the two functions:

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

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

    Inside KeyDownHandler():

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

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

    
    
    	if (isGravityPushing == true) {
    		energyM.gravityPull(player);
    	}
    	if (isGravityPushing == 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 new function to Player:

    First, in the constructor:

    
    
    			// 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;
    			}
    

    And then…

    
    
    	public function updatePower():void
    		{
    			// 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.

    We need to make this run every frame, so add this line to GameScreen.update():

    
    
    player.updatePower();
    

    Step 19: Make Energy Increase Power

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

    In GameScreen.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 GameScreen class:

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

    In the constructor, add this code:

    
    
    scoreText = new Text("Score :");
    addChild(scoreText);
    
    score = new Text(String(totalScore));
    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);
    
    			speed = speed1;
    		}
    
    		// make sure you call this every frame
    		private function moveDown():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.

    Next: Read this critique for a guide to taking Flux from a simple demo to a full game!


  5. Matt Stuttard Parker says:
    June 26, 2012 at 11:56 pm

    There are several methods used to produce menus within Unity, the main two being the built in GUI system and using GameObjects with Colliders that respond to interactions with the mouse. Unity’s GUI system can be tricky to work with so we’re going to use the GameObject approach which I think is also a bit more fun for what we’re trying to achieve here.


    Final Result Preview

    Please view the full post to see the Unity content.


    Step 1: Determine Your Game Resolution

    Before designing a menu you should always determine what resolution you are going to serve it to.

    Open the Player settings via the top menu, Edit > Project Settings > Player and enter your default screen width and height values into the inspector. I chose to leave mine as the default 600x450px as shown below.

    unity tutorial menus UI

    You then need to adjust the size of your Game view from the default "Free Aspect" to "Web (600 x 450)", else you could be positioning your menu items off the screen.

    unity tutorial menus UI

    Step 2: Choosing a Menu Background

    As you will have seen in the preview, our menu scene is going to have our game environment in the background so that when you click Play you enter seamlessly into the game.

    To do this you need to position your player somewhere in the scene where you like the background and round up the Y rotation value. This is so it’s easier to remember and to replicate later, so that the transition can be seamless from the menu into the game.

    unity tutorial menus UI

    Let’s now get on with the creation of the menu scene!


    Step 3: Creating the Menu Scene

    Make sure your scene is saved and is called "game" – you’ll see why later.

    Select the game scene within the Project view and duplicate it using Ctrl/Command + D, then rename the copy to "menu" and double-click it to open it.

    Note: You can confirm which scene is open by checking the top of the screen, it should say something like "Unity – menu.unity – ProjectName – Web Player / Stand Alone". You don’t want to start deleting parts accidently from your game scene!

    Now select and delete the GUI and PickupSpawnPoints GameObjects from the Hierarchy. Expand the "Player" and drag the "Main Camera" so that it’s no longer a child of the Player, then delete the Player.

    unity tutorial menus UI

    Next, select the terrain and remove the Terrain Collider Component by right-clicking and selecting Remove Component.

    Finally, select the "Main Camera" and remove the MouseLook Component by right-clicking and selecting Remove Component.

    If you run the game now nothing should happen and you shouldn’t be able to move at all. If you can move or rotate then redo the above steps.


    Step 4: Adjusting the Build Settings

    Currently when you build or play your game the only level included within that build is the "game" scene. This means that the menu scene will never appear. So that we can test our menu, we’ll adjust the build settings now.

    From the top menu select File > Build Settings and drag the menu scene from your Project View into the Build Settings’ "Scenes In Build" list as shown below

    unity tutorial menus UI

    (Make sure you rearrange the scenes to put "menu.unity" at the top, so that it’s the scene that’s loaded first when the game is played.)

    Perfect!


    Step 5: Adding the Play Button

    We’re going to use 3D Text for our menu, so go ahead and create a 3D Text GameObject via the top menu: GameObject > Create Other > 3D Text, then rename it "PlayBT". Set the Y rotation of the PlayBT text to match the Y rotation value of your Main Camera so that it’s facing directly at it and therefore easily readable.

    With the PlayBT selected, change the Text Mesh text property from Hello World to "Play", reduce the Character Size to 0.1 and increase the Font Size to 160 to make the text crisper.

    Note: If you want to use a font other than the default, either select the font before creating the 3D Text or drag the Font onto the 3DText’s TextMesh’s Font property and then drag the Fonts "Font Material" onto the Mesh Renderers Materials list, overwriting the existing Font Material. Quite a hassle I know!

    Finally, add a Box Collider via the top menu: Component > Physics > Box Collider. Resize the Box Collider to fit the text if it doesn’t fit it nicely.

    unity tutorial menus UI

    At this point in the tutorial you really need to have both the Scene and Game Views open at the same time since you are now going to move the PlayBT within the Scene View so that it’s centred within your Game View as shown below. I recommend first positioning it horizontally using a top down view and then revert to using a perspective view to position it vertically using the axis handles.

    unity tutorial menus UI
    unity tutorial menus UI

    So that’s our Play button all set up. Now let’s make it play!


    Step 6: The Mouse Handler Script

    Create a new JavaScript script within your scripts folder, rename it "MenuMouseHandler" and add it as a Component of the PlayBT GameObject by either dragging in directly onto PlayBT or by selecting PlayBT and dragging the script onto it’s Inspector.

    Replace the default code with the following:

    
    
    /**
    	Mouse Down Event Handler
    */
    function OnMouseDown()
    {
    	// if we clicked the play button
    	if (this.name == "PlayBT")
    	{
    		// load the game
    		Application.LoadLevel("game");
    	}
    }
      

    We’re using the MonoBehaviour OnMouseDown(…) function, invoked every time the BoxCollider is clicked by the mouse. We check whether the button clicked is called "PlayBT", and if so we use Application.LoadLevel(…) to load the "game" scene.

    Enough talk – go run it and watch your game come to life when you click Play!

    Note: If you click Play and have found yourself with a build settings error, don’t fret; you just need to check your build settings – revisit Step 4.


    Step 7: Ending the Game

    So the menu to start the game is great but the game technically never ends since when the timer runs out nothing happens… let’s fix that now.

    Open the CountdownTimer script and at the bottom of the Tick() function add the following line:

    
    
    Application.LoadLevel("menu");
      

    Now re-run your game and when the timer runs out you’ll be taken back to the menu! Easy Peasy!

    There we go – a basic menu added to our game. Now let’s make it a little more user friendly with a help screen to explain how to play.


    Step 8: Adding the Help Button

    The help button is identical to the PlayBT in practically every way, so go ahead and duplicate the PlayBT, rename it to HelpBT and position it below the Play button. Adjust the text property to say "Help" rather than "Play" and perhaps make the Font Size a little smaller as shown below – I used 100.

    unity tutorial menus UI

    Now open the MenuMouseHandler script and add the following else if block to your existing if statement.

    
    
    // if we clicked the help button
    else if (this.name == "HelpBT")
    {
        // rotate the camera to view the help &quot;page&quot;
    
    }

    If you check the preview you’ll see that when you click Help the camera rotates around to show the help menu. So, how do we do that?


    Step 9: God Save iTween

    Our camera rotation can all be done nice and cleanly in one line, thanks to iTween. Without iTween life wouldn’t be nearly as fun. As the name may give away it’s a tweening engine, built for Unity. It’s also free.

    unity tutorial menus UI

    Go ahead and open iTween within the Unity Asset store, then click Download/Import and import it all into your project. Once it’s imported you need to move the iTween/Plugins directory into the root of your Assets folder.

    unity tutorial menus UI

    You’re now all set to tween your life away!


    Step 10: Rotating the Camera

    Grab a piece of paper and a pen (or open a blank document) and make a note of your Main Camera’s Y rotation value, as circled below.

    unity tutorial menus UI

    Within the scene view rotate the camera around in whichever direction you like around the Y axis so that the Play and Help text are out of view and so that you’ve got a decent background for your help page. You can see mine below: I rotated from -152 to -8.

    unity tutorial menus UI

    Return to your MenuMouseHandler script and add the following line within the else if statement:

    
    
    iTween.RotateTo(Camera.main.gameObject, Vector3(0, -8, 0), 1.0);
    

    We use Camera.main to retrieve the main camera (defined by the "MainCamera" tag) from the scene and use iTween.RotateTo(…) to rotate the camera to a specific angle – in my case -8.

    (You need to replace the -8 within the above line with your camera’s current rotation.)

    Now go back to your scene and return your camera back to its original rotation that you wrote down at the start of this section, so that it’s facing the PlayBT. Run your game, click Help and the camera should spin around. Woo!

    Note: If you get an error about iTween not existing then you haven’t imported it properly – revisit Step 9.

    Now let’s build our Help page.


    Step 11: Building the Help Page

    Rotate your camera back to the Y rotation of your help page – in my case -8.

    Now we’re going to add a little explanation text as well as some more text to explain the different pickups and their scores. Finally, we’ll add a Back button to return to the main menu. You can arrange your page in whatever way you wish so feel free to get creative. Here we go…

    Duplicate the HelpBT, rename it HelpHeader, set its rotation to that of your camera, change the Anchor value to "upper center" and reduce the Font Size – I used 60.

    Next, copy and paste the below paragraph into the text property:

    "Collect as many Cubes as you can within the time limit.
    Watch out though, they change over time!

    Note: It’s worth noting that you can’t type multiline text into the text property; you have to type it in another program and then copy and paste it since pressing enter/return assigns the field.

    Finally remove the Box Collider and MenuMouseHandler Components within the Inspector since this text won’t need to be clickable. Hopefully you end up with something like this:

    unity tutorial menus UI

    Now drag a pickup prefab into the scene and position it on the screen. I put mine as shown below.

    unity tutorial menus UI

    Next, duplicate the HelpHeader, rename it to HelpPowerups, change the Anchor to "upper-left" and copy and paste the below paragraph into the text field.

    "Green: + 2 Points

    Pink: +/- Random Points

    Blue: Random Speed Boost"

    Reposition it so you have something like the below.

    unity tutorial menus UI

    All that’s left now is to add a Back button to return to the main menu.


    Step 12: The Help Page Back Button

    Duplicate the HelpBT, rename it BackBT, change its text to "Back", set its rotation to that of your camera and use the Scene View to reposition it within the Game View. I placed mine in the bottom corner as shown here:

    unity tutorial menus UI

    Now we just need to update our MenuMouseHandler script to handle mouse clicks from the BackBT as well. Add the following else if block to the bottom of the OnMouseDown() if statements:

    
    
    	// if we clicked the Back button
    	else if (this.name == "BackBT")
    	{
    		// rotate the camera to view the menu "page"
    		iTween.RotateTo(Camera.main.gameObject, Vector3(0, -152, 0), 1.0);
    	}
      

    This is nearly identical to the previous iTween statement, the only difference being the angle the camera is rotated to – -152 in my case. You need to change this number to the original Y rotation of your camera was (the one you wrote down, remember?)

    Now all you need to do it set your camera back to its original rotation – the value you just added to the iTween statement – so that it’s facing the main menu again.

    Run the game and your camera should spin round to reveal the help page and spin back round to the main menu. Congratulations, you’ve finished!


    Conclusion

    I hope you’ve enjoyed this Getting Started with Unity Session!

    In this part we’ve covered using GameObjects as menu items and the incredibly powerful tweening library, iTween.

    If you want an extra challenge, try using iTween to change the text colour on MouseOver and then back again on MouseExit. (You’ll find a list of Mouse handlers on this page.)

    Or add an iTween CameraFade and then fade it out when the timer runs out, then load then menu – rather than abruptly ending the game. You could then delay the call to Application.LoadLevel(...) using yield WaitForSeconds(...).

    Let me know how you get on in the comments!


  6. Kah Shiu Chong says:
    June 27, 2012 at 12:35 am
    This entry is part 3 of 3 in the series The Math and ActionScript of Curves

    We’ve tackled drawing curves, and finding their quadratic and cubic roots, as well as handy applications for using quadratic roots within games. Now, as promised, we’ll look at applications for finding cubic roots, as well as curves’ gradients and normals, like making objects bounce off curved surfaces. Let’s go!


    Example

    Let’s take a look one practical use of this math:

    In this demo, the “ship” bounces off the edges of the SWF and the curve. The yellow dot represents the closest point to the ship that lies on the curve. You can adjust the shape of the curve by dragging the red dots, and adjust the movement of the ship using the arrow keys.


    Step 1: Shortest Distance to a Curve

    Let’s consider the scenario where a point is located near a quadratic curve. How do you calculate the shortest distance between the point and the curve?

    point to quadratic distance

    Well, let’s start with Pythagoras’s Theorem.

    \[
    Let\ the\ point\ be\ (x_p,\ y_p)\\
    and\ call\ the\ closest\ point\ on\ the\ curve\ (x_c,\ y_c)\\
    Then:\\
    z^2 = x^2 + y^2\\
    z^2 = (x_c-x_p)^2 + (y_c-y_p)^2\\
    Given\ y_c=ax_c^2 + bx_c + c,\\
    z^2 = (x_c-x_p)^2 + [(ax_c^2 + bx_c + c) -y_p]^2
    \]

    You can see that we have substituted \(y_c\) with the quadratic equation. At a glance, we can see the highest power is 4. Thus, we have a quartic equation. All we need to do is to find a minimum point in this equation to give us the shortest distance from a point to a quadratic curve.

    But before that, we’ll need to understand gradients on a curve…


    Step 2: Gradient of a Curve

    Before we look at the problem of minimizing a quartic equation, let’s try to understand gradients of a curve. A straight line has only one gradient. But a quadratic curve’s gradient depends on which point on the curve we refer to. Check out the Flash presentation below:

    Drag the red dots around to change the quadratic curve. You can also play with the slider’s handle to change the position of blue dot along x. As the blue dot changes, so will the gradient drawn.


    Step 3: Gradient Through Calculus

    This is where calculus will come in handy. You may have guessed that differentiating a quadratic equation would give you the gradient of the curve.

    \[
    f(x) = ax^2+bx+c\\
    \frac{df(x)}{dx} = 2ax+b
    \]

    So \(\frac{df(x)}{dx}\) is the gradient of a quadratic curve, and it’s dependant on the \(x\) coordinate. Well, good thing we’ve got a method to handle this: diff1(x:Number) will return the value after a single differentiation.

    To draw the gradient, we’ll need an equation to represent the line, \(y=mx+c\). The coordinate of the blue point \((x_p, y_p)\) will be substituted into the \(x\) and \(y\), and the gradient of the line found through differentiation will go into \(m\). Thus the y-intercept of line, \(c\) can be calculated through some algebra work.

    Check out the AS3:

    
    
    var x:Number = s.value
    var y:Number = quadratic_equation.fx_of(s.value)
    point.x = x;
    point.y = y;
    
    /**
     * y = mx + c;
     * c = y - mx;	<== use this to find c
     */
    var m:Number = quadratic_equation.diff1(x);
    var c:Number =  y - m * x;
    
    graphics.clear();
    graphics.lineStyle(1, 0xff0000);
    graphics.moveTo(0, c);
    graphics.lineTo(stage.stageWidth, m * stage.stageWidth + c);
    

    Step 4: Coordinate Systems

    Always bear in mind of the inverted y-axis of Flash coordinate space as shown in the image below. At first glance, the diagram on right may seem like a negative gradient – but due to the inverted y-axis, it’s actually a positive gradient.

    Positive gradient.

    The same goes for the minimum point as indicated below. Because of the inverted y-axis, the minimum point in Cartesian coordinate space (at (0,0)) looks like a maximum in Flash coordinate space. But by referring to the location of origin in Flash coordinate space relative to the quadratic curve, it’s actually a minimum point.

    Positive gradient.

    Step 5: Rate of Change for Gradient

    Now let’s say I’m interested in finding the lowest point on a curve – how do I proceed? Check out the image below (both figures are in the same coordinate space).

    Positive gradient.

    In order to get the minimum point, we’ll just equate \(\frac{df(x)}{dx} = 0\), since by definition we’re looking for the point where the gradient is zero. But as shown above, it turns out that the maximum point on a curve also satisfies this condition. So how do we discriminate between these two cases?

    Let’s try differentiation of the second degree. It’ll give us the rate of change of the gradient.

    \[
    \frac{df(x)}{dx} = 2ax+b\\
    \frac{df^2(x)}{dx^2} = 2a
    \]

    I’ll explain with reference to the image below (drawn in Cartesian coordinate space). We can see that, as we increment along the x-axis, the gradient changes from negative to positive. So the rate of change should be a positive value.

    We can also see that when \(\frac{df^2(x)}{dx^2}\) is positive, there’s a minimum point on the curve. Conversely if the rate is negative, a maximum point is present.

    Rate of change in gradient.

    Step 6: Back to the Problem

    Now we are ready to solve the problem presented in Step 1. Recall the quartic equation (where the highest degree is 4) we arrived at:

    \[
    z^2 = (x_c-x_p)^2 + [(ax_c^2 + bx_c + c) -y_p]^2
    \]

    quartic curve

    The same quartic equation, plotted

    Remember, we are interested to find the minimum point on this curve, because the corresponding point on the original quadratic curve will be the point that’s at the minimum distance from the red dot.

    point to quadratic distance

    So, let’s differentiate the quartic function to get to gradient of this curve, and then equate the gradient of this quartic function to zero. You will see that the gradient is actually a cubic function. I’ll refer interested readers to Wolfram’s page; for this tutorial, I’ll just pluck the result of their algebra workings:

    \[
    \frac{d(z^2)}{dx}=
    2(x_c-x_p) + 2(ax_c^2 + bx_c + c - y_p)(2ax_c+b)\\
    \frac{d(z^2)}{dx}= 2a^2(x_c)^3+3ab(x_c)^2+(b^2+2ac-2ay_p+1)(x_c)+(bc-by_p-x_p)\\
    Equate\ gradient\ to\ 0\\
    \frac{d(z^2)}{dx}=0\\
    2a^2(x_c)^3+3ab(x_c)^2+(b^2+2ac-2ay_p+1)(x_c)+(bc-by_p-x_p)=0\\
    Compare\ with\ cubic\ equation\\
    Ax^3+Bx^2+Cx+D=0\\
    A = 2a^2\\
    B=3ab\\
    C=b^2+2ac-2ay_p+1\\
    D=bc-by_p-x_p
    \]

    Solve for the roots of this (rather messy) cubic function and we’ll arrive at the coordinates of the three blue points as indicated above.

    Next, how do we filter our results for the minimum point? Recall from the previous step that a minimum point has a rate of change that’s positive. To get this rate of change, differentiate the cubic function that represents gradient. If the rate of change for the given blue point is positive, it’s one of the minimum points. To get the minimum point, the one that we’re interested in, choose the point with the highest rate of change.


    Step 7: Sample of Output

    So here’s a sample implementation of the idea explained above. You can drag the red dots around to customise your quadratic curve. The blue dot can also be dragged. As you move the blue dot, the yellow one will be repositioned so that the distance between the blue and yellow dots will be minimum among all points on the curve.

    As you interact with the Flash presentation, there may be times where three yellow dots appear all at once. Two of these, faded out, refer to the roots obtained from the calculation but rejected because they are not the closest points on the curve to the blue dot.


    Step 8: ActionScript Implementation

    So here’s the ActionScript implementation of the above. You can find the full script in Demo2.as.

    First of all, we’ll have to draw the quadratic curve. Note that the matrix m2 will be referred to for further calculation.

    
    
    private function redraw_quadratic_curve():void
    {
        var cmd:Vector.<int> = new Vector.<int>;
        var coord:Vector.<Number> = new Vector.<Number>;
    
        //redraw curve;
        m1 = new Matrix3d(
            curve_points[0].x * curve_points[0].x, curve_points[0].x, 1, 0,
            curve_points[1].x * curve_points[1].x, curve_points[1].x, 1, 0,
            curve_points[2].x * curve_points[2].x, curve_points[2].x, 1, 0,
            0,0,0,1
        );
    
        m2 = new Matrix3d(
            curve_points[0].y, 0, 0, 0,
            curve_points[1].y, 0, 0, 0,
            curve_points[2].y, 0, 0, 0,
            0,0,0,1
        )
    
        m1.invert();
        m2.append(m1);
        quadratic_equation.define(m2.n11, m2.n21, m2.n31);
    
        for (var i:int = 0; i < stage.stageWidth; i+=2)
        {
            if (i == 0) cmd.push(1);
            else		cmd.push(2);
    
            coord.push(i, quadratic_equation.fx_of(i));
        }
    
        graphics.clear();
        graphics.lineStyle(1);
        graphics.drawPath(cmd, coord);
    }
    

    And here’s the one that implements the mathematical concept explained. c1 refers to a point randomly positioned on stage.

    
    
    private function recalculate_distance():void
    {
        var a:Number = m2.n11;
        var b:Number = m2.n21;
        var c:Number = m2.n31;
    
        /*f(x) = Ax^3 + Bx^2 +Cx + D
         */
        var A:Number = 2*a*a
        var B:Number = 3*b*a
        var C:Number = b*b + 2*c*a - 2*a*c1.y +1
        var D:Number = c * b - b * c1.y - c1.x
    
        quartic_gradient = new EqCubic();
        quartic_gradient.define(A, B, C, D);
        quartic_gradient.calcRoots();
    
        roots = quartic_gradient.roots_R;
        var chosen:Number = roots[0];
    
        if (!isNaN(roots[1]) && !isNaN(roots[2])) {
    
            //calculate gradient and rate of gradient of all real roots
            var quartic_rate:Vector.<Number> = new Vector.<Number>;
    
            for (var i:int = 0; i < roots.length; i++)
            {
                if (!isNaN(roots[i])) 	quartic_rate.push(quartic_gradient.diff1(roots[i]));
                else 					roots.splice(i, 1);
            }
    
            //select the root that will produce the shortest distance
            for (var j:int = 1; j < roots.length; j++)
            {
                //the rate that corresponds with the root must be the highest positive value
                //because that will correspond with the minimum point
                if (quartic_rate[j] > quartic_rate[j - 1]) {
                    chosen = roots[j];
                }
            }
    
            //position the extra roots in demo
            position_extras();
        }
        else {
    
            //remove the extra roots in demo
            kill_extras();
        }
        intersec_points[0].x = chosen
        intersec_points[0].y = quadratic_equation.fx_of(chosen);
    }
    

    Step 9: Example: Collision Detection

    Let’s make use of this concept to detect the overlap between a circle and a curve.

    The idea is simple: if the distance between the the blue dot and the yellow dot is less than blue dot’s radius, we have a collision. Check out the demo below. The interactive items are the red dots (to control the curve) and the blue dot. If the blue dot is colliding with the curve, it will fade out a little.


    Step 10: ActionScript Implementation

    Well, the code is quite simple. Check out the full source in CollisionDetection.as.

    
    
    graphics.moveTo(intersec_points[0].x, intersec_points[0].y);
    graphics.lineTo(c1.x, c1.y);
    
    var distance:Number= Math2.Pythagoras(
        intersec_points[0].x,
        intersec_points[0].y,
        c1.x,
        c1.y)
    
    if (distance < c1.radius)  c1.alpha = 0.5;
    else                       c1.alpha = 1.0;
    
    t.text = distance.toPrecision(3);
    

    Step 11: Bouncing Off the Curve

    So now that we know when collision will occur, let’s try to program some collision response. How about bouncing off the surface? Check out the Flash presentation below.

    You can see the ship (triangle shape), is surrounded by a circle (translucent blue). Once the circle collides with the curve, the ship will bounce off the surface.


    Step 12: Controlling the Ship

    Here’s the ActionScript to control the ship.

    
    
    public function CollisionDetection2()
    {
        /**
         * Instantiation of ship & its blue-ish circular area
         */
        ship = new Triangle();	addChild(ship);
        ship.x = Math.random() * stage.stageWidth;
        ship.y = stage.stageHeight * 0.8;
    
        c1 = new Circle(0x0000ff, 15);	addChild(c1);
        c1.alpha = 0.2;
    
        /**
         * Ship's velocity
         */
        velo = new Vector2D(0, -1);
        updateShip();
    
        stage.addEventListener(KeyboardEvent.KEY_DOWN, handleKey);
        stage.addEventListener(KeyboardEvent.KEY_UP, handleKey);
        stage.addEventListener(Event.EXIT_FRAME, handleEnterFrame);
    
        /**
         * The curve and the calculations
         */
        quadratic_equation = new EqQuadratic();
    
        curve_points = new Vector.<Circle>;
        populate(curve_points, 0xff0000, 3);
    
        intersec_points = new Vector.<Circle>;
        populate(intersec_points, 0xffff00, 3, false);
    
        redraw_quadratic_curve();
    }
    
    private function handleKey(e:KeyboardEvent):void
    {
        if (e.type == "keyDown") {
            if (e.keyCode == Keyboard.UP) isUp = true;
            else if (e.keyCode == Keyboard.DOWN) isDown = true;
            if (e.keyCode == Keyboard.LEFT) isLeft = true;
            else if (e.keyCode == Keyboard.RIGHT) isRight = true;
        }
        if (e.type == "keyUp") {
            if (e.keyCode == Keyboard.UP) isUp = false;
            else if (e.keyCode == Keyboard.DOWN) isDown = false;
            if (e.keyCode == Keyboard.LEFT) isLeft = false;
            else if (e.keyCode == Keyboard.RIGHT) isRight = false;
        }
    }
    
    private function handleEnterFrame(e:Event):void
    {
        /**
         * Control the magnitude
         */
        if (isUp) 		velo.setMagnitude(Math.min(velo.getMagnitude()+0.2, 3));
        else if(isDown)	velo.setMagnitude(Math.max(velo.getMagnitude()-0.2, 1));
    
        /**
         * Control the direction
         */
        if (isRight) velo.setAngle(velo.getAngle() + 0.03);
        else if (isLeft) velo.setAngle(velo.getAngle() - 0.03);
    
        recalculate_distance();
    
        if (distance < c1.radius) bounce();
        updateShip();
    }
    
    /**
     * Update ship's position, orientation and it's area (the blue-ish circle)
     */
    private function updateShip():void {
        ship.x += velo.x;
        ship.y += velo.y;
        ship.rotation = Math2.degreeOf(velo.getAngle());
    
        c1.x = ship.x;
        c1.y = ship.y;
    
        if (ship.x > stage.stageWidth || ship.x < 0) velo.x *= -1;
        if (ship.y > stage.stageHeight || ship.y < 0) velo.y *= -1;
    }
    

    You can see that the keyboard controls are updating flags to indicate whether the left, up, right, or down keys are being pressed. These flags will be captured by the enterframe event handler and update the magnitude and direction of the ship.


    Step 13: Calculating the Reflection Vector

    I’ve already covered the vector calculation of reflection vector in this post. Here, I shall just cover how to obtain the normal vector from gradient.

    \[
    \frac{df(x)}{dx}=gradient\\
    line\ gradient=\frac{y}{x}\\
    Assume\ gradient=0.5\\
    y=0.5\\
    x=1\\
    Vector\ of\ left\ normal=
    \begin{bmatrix}-1 \\0.5\end{bmatrix}\\
    Vector\ of\ right\ normal=
    \begin{bmatrix}1 \\-0.5\end{bmatrix}
    \]


    Step 14: ActionScript Implementation

    So the ActionScript below will implement the mathematical concept explained in the previous step. Check out the highlighted lines:

    
    
    private function bounce():void
    {
        var gradient:Number = quadratic_equation.diff1(intersec_points[0].x);
        var grad_vec:Vector2D = new Vector2D(1, gradient);
    
        var left_norm:Vector2D = grad_vec.getNormal(false);
        var right_norm:Vector2D = grad_vec.getNormal();
        var chosen_vec:Vector2D;
    
        if (velo.dotProduct(left_norm) > 0) chosen_vec = left_norm
        else 								chosen_vec = right_norm
    
        var chosen_unit:Vector2D = chosen_vec.normalise();
        var proj:Number = velo.dotProduct(chosen_unit);
    
        chosen_unit.scale(-2*proj);
    
        velo = velo.add(chosen_unit);
    }
    

    Conclusion

    Well, thanks for your time! If you’ve found this useful, or have any questions, do leave some comments.


  7. Porter says:
    June 27, 2012 at 12:44 am

    This week, Matt Porter critiques Jelly Escape, a popular new platformer developed by TawStudio Entertainment. Platformers are a dime a dozen on Flash portals, so let’s see what this one brings to the table…


    Play the Game



    Play the game at full size over on TawStudio’s site!


    Overview

    The web has always had an abundance of platformer games, thanks to Flash. Unfortunately, most of them lack any kind of serious polish. Fortunately, Jelly Escape isn’t one of them; it’s an incredibly well built platformer, and it’s clear that the developers did their homework and studied industry hit and obvious inspiration: Super Meat Boy.


    Gameplay

    Jelly Escape’s main focus is simple, quick, addicting platforming, and achieves this quite effectively. The game has a number of tricks up its sleeve to engage the player beyond the first few minutes, and the overall level of polish means players are likely to stick with the game long enough to get to that point.

    The most immediate, and engaging aspect of the game to me, is the retro feel. While there has been a surplus of retro-inspired games since the introduction of great Flash game frameworks such as Flixel and FlashPunk, most don’t take that retro-magic to the same level.

    As soon as I saw the opening animation where quarters were being popped into an arcade machine, I was hooked. Even if you’re not a hardcore fan of classic gaming, the added story is a very welcome addition, and is sure to please most.

    Level Select

    The second thing I noticed and was impressed with in Jelly Escape was the sheer number of levels the game had to offer. As soon as you start the game, you can see that there at least 60 – that’s a lot of levels! These are split into four sections of fifteen levels each, so I was pretty convinced that variety wouldn’t be an issue.

    While I do love the sheer number of levels offered, I do think all great platformers should have a world map of sorts since, to me, exploration is one of my favorite aspects of gaming. Not only is arranging 60 levels as boxes with numbers a tad boring, it straight up tells you how many levels there are, and doesn’t leave any mystery for the player. I personally love unlocking a new world when I think a game is about to be complete, and this setup just doesn’t allow for that.

    Another possible negative aspect of telling the player how many levels there are, is that they may find themselves slightly bored part way through your game and, knowing they’re nowhere near the end, just stop playing. If they thought that they might be nearly finished, they might just stick around another few levels to finish it up. During this time they may become bored and leave anyways, complete the game, or they might just hit your next big game mechanic that adds a breath of fresh air into their gaming experience, keeping them around that much longer.

    There are a few levels that can be unlocked through your actions…

    A proper compromise to having a full blown world map, versus a simple menu setup, would be to unlock new sets of levels upon the completion of a previous set. Jelly Escape has four sets, but perhaps only one needs to be seen at first; the unlocking of the others could have been used to spice up the player’s experience. Even if my love for exploration isn’t shared by all, it’s important as a developer to understand the various experiences that any gamer enjoys, so that you can be sure to fit in as many positive experiences as your game’s design will allow, and please as large an audience as possible.

    Rewards and Stats

    One of the strongest points of Jelly Escape is how much – and how often – the player is rewarded. Some of these rewards are given by playing the game well, while others are a bit more creative and are rewarded for completing actions such as following the developers on Twitter and Facebook.

    While I’m generally against gimmicks, the unlockables are purely bonus material, and truly don’t take away from the game if you pass them up – so no harm done. It’s actually a great move on the developers part, and I’ll probably use it myself in future games, as I like their implementation.

    In addition to the unlockables, the game also keeps track of a ton of stats, such as your best times and lowest death count for each level. Small features like this make for great replay value, and add a lot to the game.

    Like many games of this style, Jelly Escape keeps track of how many of a certain collectible you get in each level. This information is shown on the level select screen, and is easily to understand. Unlike certain games, this rating actually matters. Far too many games will give you a “3 star rating” system of sorts, just for the hell of it, with no real incentive for the player to go back and master levels, but Jelly Escape offers two incentives to collect the energy bolts.

    The first, which is my favorite, is that you can find characters locked up behind a gate within select levels (as shown on the level select screen), and if you’ve collected enough of the energy collectibles, you can set them free. Once free, you can use their appearance as your jelly’s skin, which is a pretty awesome addition, especially since some of the skins are based off of characters from other popular games.

    The second, is that collecting enough bolts will unlock additional challenge levels. I played a few of these myself, and they definitely had an “unlockable level” kind of feel, much like the “secret” zone found in Super Mario World. Between these two awesome incentives, I definitely felt encouraged to replay levels, rather than to just rush through the game.

    Level Design

    Level design is a strong point of Jelly Escape, as it should be with any platformer. There aren’t too many mechanics in the game, but what’s there is used very well.

    I never found the level design to be too repetitive or bland, and was actually impressed with the overall diversity. In addition, the difficulty curve seemed to be rather balanced, as few levels stood out as too hard, but it did feel like the difficulty was slowly climbing. To make things even better, levels are littered with checkpoints so that death isn’t overly punishing: an excellent addition that makes this game far more friendly with its casual target market. Plus, I never encountered any levels that were strictly tedious and not fun.

    While the level design is quite well done, some core design choices of the game do take away from the overall fun factor. The game has a rather zoomed out feel, because all of the levels are presented within a single screen. While this seems to be accepted among many platformers, I feel that a more zoomed in view, with a camera for scrolling, is the better approach. To me, this allows for more precise movement, and gives a hint of exploration during gameplay, as you can’t see everything at once.

    On the other hand, the game design often requires the levels to fit in a single screen – for example, falling through the bottom of the level simply brings you back to the top, and some levels are designed around this – so perhaps this is just a matter of my preferences getting in the way.

    I will note that Super Meat Boy isn’t limited to a single screen however, and I feel that if it had been, it would greatly deter from the experience. Perhaps this was a deliberate design choice, perhaps scrolling levels were simply a technical complexity the developers didn’t want to mess with; either way, I still feel a more zoomed-in experience would benefit the game’s design.


    Graphics

    The graphics in Jelly Escape are retro, but kick things up with with massive attention to small details in visual effects. Touching walls covers them with your jelly’s slime, and spits out particle effects. Dying makes the edges of the screen tweak out. There’s a neat lighting effect in place where you can see better around your character, and collecting energy within a level increases this effect significantly.

    The game is also very animation complete, something that is often lacking in indie platformers. The player is excellently animated, energy collectibles are animated, springs are animated; everything that should have an animation, does. All menus are very clean, and all menu items have a hover effect, which makes for a very polished game. While you may think that menus are nearly worthless in a game as simple as a platformer, retaining a polished and positive image consistently throughout the project is extremely important. If you’re not willing to polish your audio-mute button, don’t bother polishing your enemy animations, as a lack of consistency breaks the entire image.

    All in all, the graphical quality of this greatly excels because of the extreme attention to small details. No single effect is a game changer on its own, but together, they make this game look ten times better than it would without them.


    Audio

    While the audio is nothing amazing in Jelly Escape, it’s still quite well done. I find the music very fitting to the somewhat dark and ominous atmosphere, and I personally feel it’s a very good fit.

    As was the case with animations and effects for grpahics, Jelly Escape is extremely complete in the audio department. There’s sounds for literally everything. Jumping has a sound, landing has a sound, enemies hitting walls, opening gates, hitting buttons, dying, hovering over menu items; everything in the entire game has a sound, as it should be.

    To further add polish, the toggle music and sound buttons are pretty awesome looking too. Each is its own small audio visualizer, which I found very neat. This is most definitely not needed, but if I noticed it, others did too, so take note of the positive effects such features can have on a players mode, and how it can effect their perception of an author’s hard work.


    Conclusion

    Jelly Escape may have its flaws, but I haven’t played a web platformer this polished and addicting since MoneySeize, and those were great (albeit somewhat frustrating) times.

    Yikes!

    Jelly Escape doesn’t take many shortcuts. A ton of unlockables, a huge array of levels, and badges on Kongregate make the addicting qualities of the game shine brighter than ever.

    I definitely plan on revisiting the game to finish up those last 30 levels or so, as I’m a sucker for platformers; how far did you play before losing interest?


  8. Sebastian Bratu says:
    June 27, 2012 at 1:41 am

    In this Premium series, you’ll learn how to use Flash to build a Facebook Graph API application that can create slideshows for your public pages. This third part covers generating a code to load the events from a Facebook Page.


    Premium Preview

    Click to try the app on Facebook.

    This application allows you to select a Facebook album or event list from one of your public pages and turn it into a slideshow for your page tab. When the users enter your page, they will see photos from your chosen album, with your photo title and description, or event name, date and invites (for the event tab).

    In the second part, we created the embed code for the album (basically finding out the album ID from which we load the photos). This time, we are going to use the Graph API to get a list of a page’s events, based on its Page ID.

    You’ll need to be logged in to Facebook in order to see this demo: https://apps.facebook.com/activetuts_tabmaker/


    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 for free.


    Tuts+ Premium Membership

    We run a Premium membership system which periodically gives members access to extra tutorials, like this one, from across the whole Tuts+ network. If you’re a Premium member, you can log in and read 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.


  9. Kah Shiu Chong says:
    June 27, 2012 at 2:25 am
    This entry is part 2 of 3 in the series The Math and ActionScript of Curves

    In the first tutorial of this series, we took a look at drawing curves using equations and AS3. Now, we’re going to tackle solving those equations to find the roots of a curve – that is, the places where the curve crosses a given straight line. We can use this to predict collisions with curved surfaces, and to avoid “tunnelling” in Flash games.


    Step 1: Quadratic Roots

    First, time for some quick math revision. In this tutorial, we’ll just accept and apply the methods we’ll use, but interested readers can refer to Wikipedia’s page on quadratic equations for information about the mathematical deriviations.

    So \(f(x)\) is a quadratic function. If \(f(x)\) is equivalent to 0, \(x\) can be obtained by this formula:

    \[Given\ f(x)\ = \ ax^2+bx+c,\ \]
    \[f(x)\ =\ 0,\ x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} \]

    \(b^2 – 4ac\) is called the discriminant of the formula. If the discriminant is negative, the square root of the discriminant will produce imaginary roots, which we can’t plot. Conversely, if the discriminat is positive, you will have real number roots and you’ll be able to plot them onto the screen.


    Step 2: Visualising Quadratic Roots

    So what are roots? Well in our context they are nothing more than intersection points between the quadratic curve and a line. For example, suppose we are interested to find the intersection point(s) of the following set of equations:

    \(
    f(x)\ = \ ax^2+bx+c \\
    g(x)\ = \ 0
    \)

    This is a typical scenario of looking for the intersection point(s) between a quadratic curve and the x-axis (because the x-axis is the line where y==0). Since by definition the intersection point(s) are shared by \(f(x)\) and \(g(x)\), we can conclude that \(f(x) = g(x)\) for the values of x that we are looking for.

    It’s then a trivial operation where you just substitute the functions and then apply the formula from Step 1 to obtain the roots. Now there are several possibilities we can anticipate as shown below.

    Possiblities of root locations

    (As you can see, “imaginary roots” means, for our purposes, that the curve doesn’t ever cross the x-axis.)

    Now let’s consider the case where \(g(x)\) is more than just a mundane horizontal line. Let’s say it’s a slanted line, \(g(x)\ =\ mx\ +\ d\). Now when we equate both functions, we’ll need to do a little precalculation before the formula can be effectively applied.

    \[
    ax^2\ +\ bx + c\ =\ mx\ +\ d\\
    ax^2\ +\ (\ b\ - m)\ x + (c\ -\ d)\ =\ 0
    \]

    I’ve included an interactive Flash presentation below so feel free to drag the red and blue dots. Yellow dots indicate the intersection points. You may need to position the curve and line to intersect each other in order for the yellow dots to appear.


    Step 3: Plotting This With ActionScript

    The full script can be found in Demo1.as; here I’ll just explain a crucial extract of the code. Let’s look at the AS3 for drawing the curve and line:

    
    
    private function redraw():void
    {
        var cmd:Vector.<int> = new Vector.<int>;
        var coord:Vector.<Number> = new Vector.<Number>;
    
        //redraw curve;
        m1 = new Matrix3d(
            curve_points[0].x * curve_points[0].x, curve_points[0].x, 1, 0,
            curve_points[1].x * curve_points[1].x, curve_points[1].x, 1, 0,
            curve_points[2].x * curve_points[2].x, curve_points[2].x, 1, 0,
            0,0,0,1
        );
    
        m2 = new Matrix3d(
            curve_points[0].y, 0, 0, 0,
            curve_points[1].y, 0, 0, 0,
            curve_points[2].y, 0, 0, 0,
            0,0,0,1
        )
    
        m1.invert();
        m2.append(m1);
        quadratic_equation.define(m2.n11, m2.n21, m2.n31);
    
        for (var i:int = 0; i < stage.stageWidth; i+=2)
        {
            if (i == 0) cmd.push(1);
            else		cmd.push(2);
    
            coord.push(i, quadratic_equation.fx_of(i));
        }
    
        //draw line
        n1 = new Matrix();
        n1.a = line_points[0].x; n1.c = 1;
        n1.b = line_points[1].x; n1.d = 1;
    
        n2 = new Matrix();
        n2.a = line_points[0].y; n2.c = 0;
        n2.b = line_points[1].y; n2.d = 0;
    
        n1.invert();
        n2.concat(n1);
    
        var x:Number = stage.stageWidth		//y = mx + c
        cmd.push(1);	coord.push(0, n2.a * 0 + n2.b);
        cmd.push(2);	coord.push(x, n2.a * x + n2.b);
    
        graphics.clear();
        graphics.lineStyle(1);
        graphics.drawPath(cmd, coord);
    }
    

    The bulk of ActionScript for drawing the curve from line 80~104 is largely borrowed from the previous tutorial, so I shall just explain a little about the code for drawing a line.

    In the Flash presentation above, there are two interactive blue dots. Each of these has coordinates, and with both dots, a line is formed. Since both dots lie on the same line, they share a common slope and y-intercept to form one general line equation:

    \[
    y\ =\ mx\ +\ d,\\
    m\ =\ slope,\ d\ =\ y-intercept
    \]

    We can use a little algebra to solve for the two unknowns, \(m\) and \(d\). Given the coordinates of the two blue dots as \((x_1,\ y_1)\) and \((x_2,\ y_2)\):

    \(
    y_1 = mx_1 + d\\
    y_2 = mx_2 + d\\
    \)

     

    \(
    \begin{bmatrix}y_1 \\y_2\end{bmatrix} =
    \begin{bmatrix}x_1 & 1\\x_2 & 1\end{bmatrix}
    \begin{bmatrix}m \\d\end{bmatrix} \\
    \)

     

    \(
    \begin{bmatrix}x_1 & 1\\x_2 & 1\end{bmatrix}^{-1}
    \begin{bmatrix}y_1 \\y_2\end{bmatrix} =
    \begin{bmatrix}x_1 & 1\\x_2 & 1\end{bmatrix}^{-1}
    \begin{bmatrix}x_1 & 1\\x_2 & 1\end{bmatrix}
    \begin{bmatrix}m \\d\end{bmatrix} \\
    \)

     

    \(
    \begin{bmatrix}x_1 & 1\\x_2 & 1\end{bmatrix}^{-1}
    \begin{bmatrix}y_1 \\y_2\end{bmatrix} =
    I
    \begin{bmatrix}m \\d\end{bmatrix}
    \)

     

    (Note that a matrix with superscripted -1 refers to inverse of that matrix.)

    So using this, \(m\) and \(d\) are calculated. We can can now draw the line by joining the coordinates \((0, y_3)\) and \((stage.stageWidth, y_4)\). How do you find \(y_3\) and \(y_4\)? Well now that \(m\), \(x\) and \(d\) are known, we can simply put all these values into the line general equation,

    \(y\ =\ mx\ +\ d\)

    ..to get those \(y\)s.


    Step 4: Calculate the Quadratic Roots

    To calculate the position of the intersecting points, we shall use the formula from Step 1. This is done in EqQuadratic.as as the functions shown below:

    
    
    /**Read-only
     * Discriminant of equation
     */
    public function get discriminant():Number {
        //B*B-4*A*C
        return _B * _B - 4 * _A * _C;
    }
    
    /**
     * Performs calculation to obtain roots
     */
    public function calcRoots():void {
        var disc:Number = this.discriminant
    
        //handle imaginary roots
        if (disc < 0) {
            disc *= -1;
            var component_real:Number = -_B / (2 * _A);
            var component_imaginary:Number = Math.sqrt(disc) / (2 * _A);
    
            _root_i[0] = (component_real + "+ i" + component_imaginary).toString();
            _root_i[1] = (component_real + "- i" + component_imaginary).toString();
        }
    
        //handle real roots
        else {
            var sqrt:Number = Math.sqrt(disc);
            _root_R[0] = ( -_B + sqrt) / (2 * _A);
            _root_R[1] = ( -_B - sqrt) / (2 * _A);
        }
    }
    

    Further details of EqQuadratic.as:

    Function Type Input Parameter Functionality
    EqQuadratic Method Nil Class constructor
    define Method Coefficients a, b and c of quadratic equation Instantiate the coefficient values
    fx_of Method Value of x Returns \(f(x)\) of given \(x\) input.
    calcRoots Method Nil Performs calculation to obtain quadratic root
    diff1 Method \(x\) coordinate for the first degree differentiation Differentiated \(f(x)\) of given \(x\) at the first degree.
    diff2 Method \(x\) coordinate for the second degree differentiation Differentiated \(f(x)\) of given \(x\) at the second degree.
    discriminat Property, read only Nil Returns the value of discriminant, \(b^2 – 4ac\)
    roots_R Property, read only Nil Returns a Number vector for roots of real number. Elements are NaN if no real roots exist.
    roots_i Property, read only Nil Returns a String vector for roots of imaginary number. Elements are null if no imaginary roots exist.

    Step 5: Plotting This With ActionScript

    An example of utilising this EqQuadratic.as is in Demo1.as. After the initiation of EqQuadratic, we shall use it to calculate the roots. Then, after validating the presence of real roots, we’ll use them to plot the yellow dots.

    Now the roots refer to only the \(x\) component of the coordinates. To obtain the \(y\)s, guess what? Again, we put the values of \(m\), \(d\) (calculated earlier in Step 3) and \(x\) (from the roots) into the line general equation, \(y\ =\ mx\ +\ d\). Check out the corresponding code in line 135 and 136.

    
    
    private function recalculate_reposition():void
    {
        quadratic_equation.define(m2.n11, m2.n21 - n2.a, m2.n31 - n2.b);
        quadratic_equation.calcRoots();
    
        var roots:Vector.<Number> = quadratic_equation.roots_R;
    
        if (!isNaN(roots[0]) && !isNaN(roots[1])) {
            intersec_points[0].x = roots[0]; intersec_points[0].y = n2.a * roots[0] + n2.b
            intersec_points[1].x = roots[1]; intersec_points[1].y = n2.a * roots[1] + n2.b
        }
        else {
            intersec_points[0].x = -100; intersec_points[0].y = -100;
            intersec_points[1].x = -100; intersec_points[1].y = -100;
        }
    }
    

    Step 6: Cubic Roots

    Cubic roots, not surprisingly, are the intersection points between a cubic curve and a line. But a cubic curve is a little different to a quadratic curve, and in this respect the possibilities for where intersections could be located are different.

    The image below shows a cubic curve intersecting with the x-axis:

    Possiblities of root locations on a cubic curve

    Again, here’s a little Flash presentation for you to experiment with. Red and blue dots can be dragged while the yellow ones just indicate the intersection points.


    Step 7: General Formula for Cubic Roots

    The general formula to find a cubic curve was discovered by Cardano. Although I’m enticed to elaborate on the details, I’ll just point interested readers to the following links:

    • Wikipedia
    • Wolfram, and
    • Another userful PDF file.

    Anyway, the EqCubic.as class implements this formula to resolve roots of cubic functions along with other mathematical utility functions. Generally all the attributes and methods for EqCubic.as follow the desciption as tabled in Step 4, because both classes EqQuadratic.as and EqCubic.as implement one common interface, IEquation.as, except for the details listed below.

    Function Difference
    define A total of four coefficients (a, b, c, d) to input for cubic equation; just three for quadratic equation.
    roots_R, root_i The total of real and imaginary roots is three for a cubic equation, but two for a quadratic equation.

    Step 8: Plotting This With ActionScript

    Here’s the Actionscript implementation for the Flash presentation from Step 5. The full code is in Demo3.as.

    
    
    private function redraw():void
    {
        var cmd:Vector.<int> = new Vector.<int>;
        var coord:Vector.<Number> = new Vector.<Number>;
    
        //redraw curve;
        m1 = new Matrix3d(
            curve_points[0].x * curve_points[0].x * curve_points[0].x, curve_points[0].x * curve_points[0].x, curve_points[0].x, 1,
            curve_points[1].x * curve_points[1].x * curve_points[1].x, curve_points[1].x * curve_points[1].x, curve_points[1].x, 1,
            curve_points[2].x * curve_points[2].x * curve_points[2].x, curve_points[2].x * curve_points[2].x, curve_points[2].x, 1,
            curve_points[3].x * curve_points[3].x * curve_points[3].x, curve_points[3].x * curve_points[3].x, curve_points[3].x, 1
        );
    
        m2 = new Matrix3d(
            curve_points[0].y, 0, 0, 0,
            curve_points[1].y, 0, 0, 0,
            curve_points[2].y, 0, 0, 0,
            curve_points[3].y, 0, 0, 0
        )
    
        m1.invert();
        m2.append(m1);
        cubic_equation.define(m2.n11, m2.n21, m2.n31, m2.n41);
    
        for (var i:int = 0; i < stage.stageWidth; i+=2)
        {
            if (i == 0) cmd.push(1);
            else		cmd.push(2);
    
            coord.push(i, cubic_equation.fx_of(i));
        }
    
        //draw line
        n1 = new Matrix();
        n1.a = line_points[0].x; n1.c = 1;
        n1.b = line_points[1].x; n1.d = 1;
    
        n2 = new Matrix();
        n2.a = line_points[0].y; n2.c = 0;
        n2.b = line_points[1].y; n2.d = 0;
    
        n1.invert();
        n2.concat(n1);
    
        var x:Number = stage.stageWidth		//y = mx + c
        cmd.push(1);	coord.push(0, n2.a * 0 + n2.b);
        cmd.push(2);	coord.push(x, n2.a * x + n2.b);
    
        graphics.clear();
        graphics.lineStyle(1);
        graphics.drawPath(cmd, coord);
    }
    

    Again, the ActionScript commands to draw a cubic curve are exactly the same as explained in my previous article, whereas Actionscript commands to draw the line are already explained in Step 3 of this one.

    Now let’s move on to calculating and positioning the cubic roots:

    
    
    private function recalculate_reposition():void
    {
        cubic_equation.define(m2.n11, m2.n21 , m2.n31 - n2.a, m2.n41 - n2.b);
        cubic_equation.calcRoots();
    
        var roots:Vector.<Number> = cubic_equation.roots_R;
    
        for (var i:int = 0; i < roots.length; i++)
        {
            if (!isNaN(roots[i])) {
                intersec_points[i].x = roots[i]; intersec_points[i].y = n2.a * roots[i] + n2.b
            }
            else {
                intersec_points[i].x = -100; intersec_points[i].y = -100;
            }
        }
    }
    

    After instantiating cubic_equation in the constructor we proceed on to define its coefficients, calculate the roots, and store the roots in a variable.

    One little note on the roots: there are a maximum of three real roots for a cubic equation, but not all real roots are present in all situation as some roots may be imaginary. So what happens when there’s only one real root, for example? Well, one of the array of roots called from cubic_equation.roots_R will be a real number, while all the others will be Not a Number (NaN). Check out the highlighted ActionScript for this.


    Step 9: Predicting Where an Object Will Collide With Curved Surface

    A great application of calculating roots is projecting a collision point onto curved surface, as show below. Use the left and right arrow keys to steer the moving ship, and press up to accelerate. You will notice that collision points which would have happened in the past are slightly dimmed.


    Step 10: Implementation

    The idea is similar to that in my tutorial about predicting collision points. However, instead of colliding with a straight line, we’re now using a curved line. Let’s check out the code.

    The snippet below is called every frame:

    
    
    private function update(e:Event):void
    {
        //Steering left and right
        if (control == 1)  velo = velo.rotate(Math2.radianOf(-5));
        else if (control == 2)  velo = velo.rotate(Math2.radianOf(5));
    
        //manipulating velocity
        var currVelo:Number = velo.getMagnitude();
        if (increase == 0)  {
            currVelo -= 0.5; currVelo = Math.max(currVelo, 1); //lower bound for velocity
        }
        else if (increase == 1)  {
            currVelo += 0.5; currVelo = Math.min(currVelo, 5); //upper bound for velocity
        }
        velo.setMagnitude(currVelo);
    
        //update velocity
        ship.x += velo.x; ship.y += velo.y; ship.rotation = Math2.degreeOf(velo.getAngle());
    
        //reflect when ship is out of stage
        if (ship.x <0 || ship.x > stage.stageWidth) velo.x *= -1;
        if (ship.y <0 || ship.y > stage.stageHeight) velo.y *= -1;
    
        redraw();
        recalculate();
    }
    

    The core code lies in redraw and recalculate. Let’s first see what’s in redraw. It’s the same one we had been using in previous demos. One little note on drawing the line. We saw in previous demos that two dots are needed to draw get the equation. Well, here we only have one ship. So to get the second point, just add the ship’s velocity to its current position. I’ve highlighted the code for convenience.

    
    
    private function redraw():void
    {
        var cmd:Vector.<int> = new Vector.<int>;
        var coord:Vector.<Number> = new Vector.<Number>;
    
        //redraw curve;
        m1 = new Matrix3d(
            w1.x * w1.x, w1.x, 1, 0,
            w2.x * w2.x, w2.x, 1, 0,
            w3.x * w3.x, w3.x, 1, 0,
            0,0,0,1
        );
    
        m2 = new Matrix3d(
            w1.y, 0, 0, 0,
            w2.y, 0, 0, 0,
            w3.y, 0, 0, 0,
            0,0,0,1
        )
    
        m1.invert();
        m2.append(m1);
        quadratic_equation.define(m2.n11, m2.n21, m2.n31);
    
        minX = Math.min(w1.x, w2.x, w3.x);
        maxX = Math.max(w1.x, w2.x, w3.x);
    
        for (var i:int = minX; i < maxX; i+=2)
        {
            if (i == minX) cmd.push(1);
            else		cmd.push(2);
    
            coord.push(i, quadratic_equation.fx_of(i));
        }
    
        n1 = new Matrix();
        n1.a = ship.x; 			n1.c = 1;
        n1.b = ship.x + velo.x; n1.d = 1;
    
        n2 = new Matrix();
        n2.a = ship.y; 			n2.c = 0;
        n2.b = ship.y + velo.y; n2.d = 0;
    
        n1.invert();
        n2.concat(n1);
    
        var x:Number = stage.stageWidth		//y = mx + c
        cmd.push(1);	coord.push(0, n2.a * 0 + n2.b);
        cmd.push(2);	coord.push(x, n2.a * x + n2.b);
    
        graphics.clear();
        graphics.lineStyle(1);
        graphics.drawPath(cmd, coord);
    }
    

    Now for recalculate, I’ve done a little vector calculation to check whether the point is behind or in front of the ship. Check out the highlighted code:

    
    
    private function recalculate():void
    {
        quadratic_equation.define(m2.n11, m2.n21 - n2.a, m2.n31 - n2.b);
        quadratic_equation.calcRoots();
    
        var roots:Vector.<Number> = quadratic_equation.roots_R;
    
        for (var i:int = 0; i < roots.length; i++)
        {
            var reposition:Sprite = getChildByName("c" + i) as Sprite
    
            //conditions:
            //real root, value of x within the range
            if (!isNaN(roots[i]) && roots[i] > minX && roots[i] < maxX) {
                reposition.x = roots[i];
                reposition.y = n2.a * roots[i] + n2.b;
    
                //discriminating between future and already happened collision point
                var vec:Vector2D = new Vector2D(reposition.x - ship.x, reposition.y - ship.y);
                if (velo.dotProduct(vec) < 0) 	reposition.alpha = 0.4;
                else 							reposition.alpha = 1
            }
            else {
                reposition.x = -100; reposition.y = -100;
            }
        }
    }
    

    Step 11: Time-Based Collision Detection

    Another great application is not quite as obvious as the first. To perform a more accurate collision detection, instead of basing our conclusion on the distance between two objects, we’ll uae their time to impact. Why? Because “tunneling” can happen if we use distance based collision detection:

    tunelling

    Consider a collision detection algorithm that’s based on distance for two circles. Of the four frames shown, only frame 2.15 successfully detected collision between two circles. Why? Because the current distance between the gray and the red circles’ centers is less than the sum of both circles’ radii.

    (Readers interested on more details on this topic can refer to this article.)

    \[distance\ between\ circles\ < \ radius_{red}\ +\ radius_{gray}\]

    The problem is caused by how Flash proceeds by one discrete frame at a time, which means that only frames 1, 2, and 3 will be successfully captured, and not the moments in between thos snapshots of time. Now the gray and red circles did not collide in these frames according to a distance-based calculation, so the red circle tunnels right through the gray one!

    To fix this, we need a way to see the collision that occurred between frames 2 and 3. We need to calculate the time to impact between two circles. For example, once we check that time to impact is less than 1 frame at frame 2, this means that once Flash proceeds 1 frame forward collision or even tunneling will have definitely had taken place.

    \[if\ time\ to\ impact,\ t,\ fulfills\ 0\ < \ t\ <\ 1,\ tunneling\ will\ happen\ next\ frame\]

    The question is, how do we calculate this time?


    Step 12: Precalculations

    collision between 2 circles.

    I’ll try to show my method as simply as possible.

    Given the scenario above, the two gray and red circles are currently located at \((x_{gray},\ y_{gray})\) and \((x_{red},\ y_{red})\). They are moving at \(v_{gray}\) and \(v_{red}\) respectively, and set on a collision path. We are interested to calculate the time taken, \(t\), for them to reach positions \((x’_{gray},\ y’_{gray})\) and \((x’_{red},\ y’_{red})\), indicated by the translucent gray and red circles, where the collision occurred.

    \[
    displacement_{future} = displacement_{present}+velocity*time\\
    x'_{gray}=x_{gray}+v_{gray_x}*t\ ...(eq.\ 1)\\
    y'_{gray}=y_{gray}+v_{gray_y}*t\ ...(eq.\ 2)\\
    x'_{red}=x_{red}+v_{red_x}*t\ ...(eq.\ 3)\\
    y'_{red}=y_{red}+v_{red_y}*t\ ...(eq.\ 4)
    \]

    Note that I’ve derived the horizontal and vertical components of \(v_{gray}\) into \(v_{gray_x}\) and \(v_{gray_y}\). Same goes with velocity of the red circle; check out this Quick Tip to get to know how these components are derived.

    We still lack one relationship to bind all these equations together. Let’s see the image below.

    When collision happened.

    The other relationship goes back to Pythagoras. When both circles meet, the distance between both centers is exactly \(rad_{gray}\) plus \(rad_{red}\).

    \[
    Pythagoras'\ Theorem,\ z^2=x^2+y^2\\
    (rad_{gray}+rad_{red})^2=(x'_{gray}-x'_{red})^2+(y'_{gray}-y'_{red})^2\ ...(eq.\ 5)\\
    \]

    This is where you substitute equations 1~4 into equation 5. I understand its quite daunting mathematically, so I’ve separated it out into Step 13. Feel free to skip it to arrive at the result at Step 14.


    Step 13 (Optional): Mathematical Rigour

    First, we establish the following identities.

    \[
    Identity,\\
    (a+b)^2=a^2+2ab+b^2\ ...(id.\ 1)\\
    (a-b)^2=a^2-2ab+b^2\ ...(id.\ 2)\\
    \]

    At all times, bear in mind that all mathematical symbols represent a constant except for time, \(t\), which is the subject of interest.

    \(x_{gray},\ v_{gray_x},\ y_{red}, \) and so on are all defined in the scenario.

    Next, we’ll try to break our problem down term by term:

    \[
    (rad_{gray}+rad_{red})^2=(x'_{gray}-x'_{red})^2+(y'_{gray}-y'_{red})^2\\
    Consider\ term\ (x'_{gray}-x'_{red})^2\ and\ utilising\ id.\ 2\\
    (x'_{gray}-x'_{red})^2 = (x'_{gray})^2-2(x'_{gray})(x'_{red})+(x'_{red})^2\\
    \]
    \[
    Consider\ term\ (x'_{gray})^2\\
    (x'_{gray})^2\\
    =(x_{gray}+v_{gray_x}*t)^2,\ utilise\ id.\ 1\\
    =(x_{gray})^2+2(x_{gray})(v_{gray_x}*t)+(v_{gray_x}*t)^2
    \]
    \[
    Consider\ term\ -2(x'_{gray})(x'_{red})\\
    -2(x'_{gray})(x'_{red})\\
    =-2(x_{gray}+v_{gray_x}*t)(x_{red}+v_{red_x}*t)\\
    =-2[(x_{gray})(x_{red})+(x_{gray})(v_{red_x}*t)+(v_{gray_x}*t)(x_{red})+(v_{gray_x}*t)(v_{red_x}*t)]\\
    =-2(x_{gray})(x_{red})-2(x_{gray})(v_{red_x}*t)-2(v_{gray_x}*t)(x_{red})-2(v_{gray_x}*t)(v_{red_x}*t)
    \]
    \[
    Consider\ term\ (x'_{red})^2\\
    (x'_{red})^2\\
    =(x_{red}+v_{red_x}*t)^2,\ utilise\ id.\ 1\\
    =(x_{red})^2+2(x_{red})(v_{red_x}*t)+(v_{red_x}*t)^2
    \]

    Now at a glance, we can easily see the highest power of \(t\) is 2. So we have ourselves a quadratic equation. Let’s collect all the coefficients contributed by these three terms according to their powers.

    \(t^2\) \(t\) \(t^0=1\)
    \((v_{gray_x})^2\) \(2(x_{gray})(v_{gray_x})\) \((x_{gray})^2\)
    \(-2(v_{gray_x})(v_{red_x})\) \(-2(x_{gray})(v_{red_x})-2(v_{gray_x})(x_{red})\) \(-2(x_{gray})(x_{red})\)
    \((v_{red_x})^2\) \(2(x_{red})(v_{red_x})\) \((x_{red})^2\)

    Let’s analyse the coefficients with \(t^2\) and \(t^0\).

    \[
    (v_{gray_x})^2-2(v_{gray_x})(v_{red_x})+(v_{red_x})^2,\ recall\ id.\ 2\\
    (v_{gray_x})^2-2(v_{gray_x})(v_{red_x})+(v_{red_x})^2 = (v_{gray_x}-v_{red_x})^2
    \]
    \[
    (x_{gray})^2-2(x_{gray})(x_{red})+(x_{red})^2,\ recall\ id.\ 2\\
    (x_{gray})^2-2(x_{gray})(x_{red})+(x_{red})^2 = (x_{gray}-x_{red})^2
    \]

    And that of \(t\).

    \[
    Simplify\\
    a=(x_{gray}),\ b=(v_{gray_x})\\
    c=(v_{red_x}),\ d=(x_{red})\\
    2ab-2ac-2bd+2dc\\
    =2[ab-ac-bd+dc]\\
    =2[a(b-c)-d(b-c)]\\
    =2[(b-c)(a-d)]\\
    Resubstitute\\
    2[(b-c)(a-d)] = 2(v_{gray_x}-v_{red_x})(x_{gray}-x_{red})
    \]

    Let’s summarise in term of \((x’_{gray}-x’_{red})^2\)

    \[
    (x'_{gray}-x'_{red})^2\\
    =(v_{gray_x}-v_{red_x})^2*t^2+2(v_{gray_x}-v_{red_x})(x_{gray}-x_{red})*t +(x_{gray}-x_{red})^2
    \]

    Note that this only caters for one term in \(eq.\ 5\). We’ll need to perform the same process for another term \((y’_{gray}-y’_{red})^2\). Since they have the same algebraic form, the result should also be the same.
    \[
    (y'_{gray}-y'_{red})^2\\
    =(v_{gray_y}-v_{red_y})^2*t^2+2(v_{gray_y}-v_{red_y})(y_{gray}-y_{red})*t +(y_{gray}-y_{red})^2
    \]

    Thus after rearrangement in terms of \(t\), \(eq.\ 5\) should be as follow.

    \[
    (rad_{gray}+rad_{red})^2=(x'_{gray}-x'_{red})^2+(y'_{gray}-y'_{red})^2\\
    p=v_{gray_x}-v_{red_x}\\
    q=x_{gray}-x_{red}\\
    r=v_{gray_y}-v_{red_y}\\
    s=y_{gray}-y_{red}\\
    (p^2+r^2)*t^2+2(pq+rs)*t+(q^2+s^2-(rad_{gray}+rad_{red})^2) = 0
    \]


    Step 14: The Result

    So from the previous step, through rigourous algebra we arrived at the following formula:

    \[
    p=v_{gray_x}-v_{red_x}\\
    q=x_{gray}-x_{red}\\
    r=v_{gray_y}-v_{red_y}\\
    s=y_{gray}-y_{red}\\
    (p^2+r^2)*t^2+2(pq+rs)*t+(q^2+s^2-(rad_{gray}+rad_{red})^2) = 0
    \]

    Now this is one huge quadratic formula. We’ll try to group the coefficients into that accepted by EqQuadratic. Compare the two forms:

    \[
    ax^2+bx+c = 0\\
    (p^2+r^2)*t^2+2(pq+rs)*t+(q^2+s^2-(rad_{gray}+rad_{red})^2) = 0\\
    a = p^2+r^2)\\
    b = 2(pq+rs)\\
    c = (q^2+s^2-(rad_{gray}+rad_{red})^2)
    \]


    Step 15: Sample Implementation

    So here’s a Flash presentation to demonstrate the idea. You will see two particles on the stage, one gray and the other red. Both are connected to an arrow, indicating the magnitude and direction of velocity.

    • Click the "Next" button to progress one frame in time.
    • Click the "Back" button to revert one frame in time.

    To alter the velocity of the particles, press:

    • “Up” and “down” to increase and decrease the velocity’s magnitude, respectively.
    • “Left” and “right” to rotate the velocity.
    • "N" to switch which circle you control.

    Finally, to toggle visibility of the arrows, press "V"


    Step 16: A Note on the Quadratic Roots

    There are two roots to the quadratic equation. In this context, we are interested in the real roots. However if the two particles are not set on collision path (both paths are parallel to each other), then imaginary roots will be produced instead of real roots. In this case, both real roots will remain NaN.

    If both particles are set on a collision path, we will get two real roots. But what do these two roots represent?

    Recall in Step 12 that we made used of Pythagoras’s Theorem to tie \((x’_{gray},\ y’_{gray})\) and \((x’_{red},\ y’_{red})\) together into an equation. Well, there are two situations where the distance between two circles’ centers are exactly the sum of both radii: one before collision and one after collision. Take a look at this image:

    Reasoning two roots.

    So which one do we choose? Obviously the first because we’re not interested in the instance after collision. So we should always choose the lesser value of both roots and evaluate it. If the value is positive and less than 1, a collision will happen during the next frame. If the value is negative, the collision happened in the past.


    Step 17: The ActionScript Explained

    Let’s look at the Actionscript implemented for this example. First, the variables.

    
    
    //c1 is the gray circle
    //c2 is the red circle
    private var c1:Circle, c2:Circle;
    
    //v1 is the gray circle's velocity
    //v2 is the red circle's velocity
    private var v1:Vector2D, v2:Vector2D, toggle:Boolean = true, usingV1:Boolean = true;
    
    //tri1 will form the arrowhead of the v1
    //tri2 will form the arrowhead of the v2
    private var tri1:Triangle, tri2:Triangle;
    private var container:Sprite;
    private var eq:EqQuadratic;
    

    Then the calculation of roots. You may want to cross check the following ActionScript with the variables above.

    
    
    var p:Number = v1.x - v2.x;
    var q:Number = c1.x - c2.x;
    var r:Number = v1.y - v2.y;
    var s:Number = c1.y - c2.y;
    
    var a:Number = p * p + r * r;
    var b:Number = 2 * (p * q + r * s);
    var c:Number = q * q + s * s - (c1.radius + c2.radius) * (c1.radius + c2.radius);
    eq.define(a, b, c);
    eq.calcRoots();
    var roots:Vector.<Number> = eq.roots_R;
    

    Here’s how you should interpret the roots:

    
    
    //if no real roots are available, then they are on not on collision path
    if (isNaN(roots[0]) && isNaN(roots[1])) {
        t.text = "Particles not on collision path."
    }
    else {
        var time:Number = Math.min(roots[0], roots[1])
        var int_time:int = time * 1000;
        time = int_time / 1000;
    
        t.text = "Frames to impact: "+time.toString() + "\n";
        if(time>1) t.appendText("Particles are closing...")
        else if (time > 0 && time < 1)  t.appendText("Particles WILL collide next frame!")
        else if (time < 0) t.appendText("Collision had already happened.");
    }
    

    Conclusion

    So now we’ve studied quadratic and cubic roots in ActionScript, as well as taking a close look at two examples of how we can use the quadratic roots.

    Thanks for taking the time to read this tutorial. Do leave a comment if you see other applications of quadratic roots (or any errors!)


  10. Collis says:
    June 27, 2012 at 2:27 am

    It’s been about 6 months since we launched our much improved New Tuts+ Premium complete with courses and eBooks. In that time we’ve added 97 hours of video training, 36 eBooks and of course our premium tutorial library has continued to grow and is rapidly apporaching 1000 tutorials, including lots of fantastic Activetuts+ content. Now, for a limited time only, thanks to PayPal we’re offering anyone who joins Tuts+ Premium with a yearly membership via the PayPal service, a $50 cash back to their PayPal account. It’s a good way to get an even better deal on Tuts+ Premium yearly subscriptions!

    Join Tuts+ Premium

    If you’re serious about skilling up, head over to Tuts+ Premium and invest in yourself and your development! We’re constantly adding more content and it’s only getting better and better, so buying a yearly subscription is worth it. Plus we have a money back guarantee in the first month, so if you discover it’s not for you, you can always bail out without charge (and of course without the $50 cash!) If you enjoy our free Tuts+, you’ll definitely find Tuts+ Premium a valuable edition.

    Read the terms below and Join Tuts+ Premium today!


    Terms – read these!

    Disclaimer:PayPal is not responsible for the promotion offered by Envato and you should read the Terms & Conditions below. The PayPal service is provided by PayPal Australia Pty Limited (ABN 93 111 195 389) which holds an Australian Financial Services Licence, number 304962. Before deciding to sign-up for or use the PayPal service you should consider the Combined Financial Services Guide and Product Disclosure Statement, available at http://www.paypal.com.au.

    • The promotion is run by Envato Pty Ltd and the promotion period runs from 12.00 noon on 12 June (Australian Eastern Standard Time – AEST) until 11.59am on 19 June (AEST).
    • If you purchase a yearly $180 USD Tuts+ Premium subscription using a PayPal account during the promotion period, you will receive a $50 USD credit to that PayPal account.
    • Sorry, but existing Tuts+ Premium yearly members are not eligible for the promotion. Existing Tuts+ Premium monthly members who upgrade to a yearly subscription are eligible.
    • Payment must be made through PayPal for the promotion to apply.
    • Your PayPal account must be in good standing at time of purchase (e.g. not limited, closed or otherwise restricted).
    • The credit will be applied to the PayPal account used to purchase the yearly subscription, and will be made 45 days after the promotion period ends.
    • The credit will not be given if you exercise the Tuts+ Premium 30 day money back guarantee.
    • You may only take advantage of this promotion for one time, meaning one $50 credit per person.
    • The credit will not be given if there is a reversal, chargeback or fraudulent transaction on the subscription payment.
    • Play fair! Any attempt to defraud Envato may result in immediate disablement of your Tuts+ Premium subscription accounts. And there will be no refund on the Tuts+ Premium subscription. We will have the final say on whether there has been an attempt to defraud Envato.
    • This promotion cannot be used in conjunction with any other promotional offer or coupon.

    Upgrades

    If you are an existing monthly Tuts+ Premium member, and interested in upgrading to a yearly membership to take advantage of this offer, be sure to cancel your existing monthly subscription via PayPal. Also, thank you for being a member!!


Leave a Reply

Click here to cancel reply.

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