logo
468x60-2-495


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

Workshop: Flux – Critique

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 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 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, grabbing 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. They 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…



View full post on Activetuts+

banner ad

10 Responses to “Workshop: Flux – Critique”

  1. Porter says:
    June 25, 2012 at 5:00 am

    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 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 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, grabbing 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. They 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…


  2. Wilson Lim says:
    June 25, 2012 at 5:56 am

    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);
    
    				addEventListener(Event.ENTER_FRAME, move);	
    
    				rSpeed = speed;
    			}
    
    			// runs every frame
    			public function move(e:Event):void
    			{
    				this.y += rSpeed;
    				//rotation speed is linked to moving speed
    				this.rotation += rSpeed / 8;
    			}
    		}
    	}
    

    Step 3: The StageController Class

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

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

    Create the class:

    
    
    package
    {
    	import flash.display.Stage;
    
    	public class StageController
    	{
    		public static var STAGE:Stage;
    
    		public function StageController(stg:Stage)
    		{
    			// we will pass the stage from the Main class
    			STAGE = stg;
    		}
    	}
    }
    

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


    Step 4: Update The Main Class

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

    
    
    package
    {
    	import flash.display.Sprite;
    	import flash.events.Event;
    
    	[SWF(width = "550", height = "600")]
    
    	public class Main extends Sprite
    	{
    		private var stageController:StageController;
    
    		public function Main():void
    		{
    			stageController = new StageController(stage);
    		}
    	}
    }
    

    Step 5: Introducing a Manager Class

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

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

    
    
    package
    {
    	import flash.display.MovieClip;
    
    	public class EnergyManager
    	{
    		public var energy:Energy;
    		// this Vector will store all instances of the Energy class
    		private var energyList:Vector.<Energy>	
    
    		public function EnergyManager()
    		{
    			energyList = new Vector.<Energy>;
    		}
    	}
    }
    

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


    Step 6: Creating Energy

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

    
    
    	public function createEnergy(number:int):void
    	{
    		for (var i:int = 0; i < number; i++) {		
    
    			energy = new Energy(4);				
    
    			StageController.STAGE.addChild(energy);
    
    			energyList.push(energy);				
    
    			energy.x = Calculation.generateRandomValue(30, 520);
    			energy.y = Calculation.generateRandomValue( -150, -20);
    		}
    	}
    

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

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

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

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

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


    Step 7: Spawning Energy

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

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

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

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

    Step 8: Creating Player

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

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

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

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

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

    playerandenergy.

    Step 9: Moving the Player

    There are basically two ways to apply movement:

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

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

    There are three simple steps to doing this:

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

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

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

      Keep the player within the bounds of the screen:

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

    Here’s how all that looks, in place:

    
    
    package
    {
        import flash.display.MovieClip;
        import flash.display.Stage;
        import flash.events.Event;
        import flash.events.TimerEvent;
        import flash.ui.Keyboard;
        import flash.utils.Timer;
        import flash.events.KeyboardEvent;
    
        public class StageController
        {
            public static var STAGE:Stage;    // A variable that store Stage class type.
            public var player:Player;
    
            private var energyM:EnergyManager;
    
            private var moveRight:Boolean = false;
            private var moveLeft:Boolean = false;
            private var space:Boolean = true;
    
            private var returnedPower:int = 0;
    
            private var scoreText:Text;
            private var totalScore:int=0;
            private var score:Text;
    
            public function StageController(stg:Stage)   // Passing the stage from calling.
            {
                STAGE = stg;        // store "stage" passed to STAGE (we will pass from Main class).
                scoreText = new Text("Score :");
                STAGE.addChild(scoreText);
    
                energyM = new EnergyManager;
    
                var spawnTimer:Timer = new Timer(3000, 0);
                spawnTimer.addEventListener(TimerEvent.TIMER, spawnEnergy);
                spawnTimer.start();
    
                player = new Player;
                STAGE.addChild(player);
                player.x = 275;
                player.y = 450;
    
                STAGE.addEventListener(Event.ENTER_FRAME, update);
                STAGE.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler);
                STAGE.addEventListener(KeyboardEvent.KEY_UP, KeyUpHandler);
            }
    
    	private function KeyDownHandler(e:KeyboardEvent):void
    	{
    		if (e.keyCode == Keyboard.RIGHT) {
    			moveRight = true;
    		}
    		if (e.keyCode == Keyboard.LEFT) {
    			moveLeft = true;
    		}
    		if (e.keyCode == Keyboard.SPACE) {
    			if (space == true) {
    				space = false;
    			}else if (space == false) {
    				space = true;
    			}
    		}
    	}
    
    	private function KeyUpHandler(e:KeyboardEvent):void
    	{
    		if (e.keyCode == Keyboard.RIGHT) {
    			moveRight = false;
    		}
    		if (e.keyCode == Keyboard.LEFT) {
    			moveLeft = false;
    		}
    	}
    
    	private function update(e:Event):void
    	{
    		if (player.x >= 525) {
    			moveRight = false;
    		}
    		if (player.x <= 20) {
    			moveLeft = false;
    		}
    		if (moveRight == true) {
    			player.x += 6;
    		}
    		if (moveLeft == true) {
    			player.x -= 6;
    		}
    	}
        }
    }
    

    Step 10: Collision Detection

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

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

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

    We can write the function as below:

    
    
    	public function checkCollision(p:Player):int
    	{
    		// energy transferred due to collision
    		var energyTransfer:int = 0;
    
    		for (var i:int = 0; i < energyList.length; i++) {
    			var energyS:Energy = energyList[i];
    
    			var newX:Number = p.x - energyS.x;
    			var newY:Number = p.y - energyS.y;
    
    			var distance:Number = Math.sqrt(newX * newX + newY * newY);
    
    			if (distance <= 28) {
    				StageController.STAGE.removeChild(energyS);
    				energyList.splice(i, 1);
    				// for this simple game, we'll always transfer 1 unit
    				// but you could alter this based on speed of collision
    				// or any other factor
    				energyTransfer = 1;
    			}
    		}
    		return energyTransfer;
    	}
    
    • Line 32: note that we pass in a reference to the player, so that we can access its position.
    • Line 38: EnergyS is short for Energy Supply.
    • Line 40 & 41: finding the difference in x- and y-coordinates between the player and the energy supply we are currently checking.
    • Line 43: calculate the distance between the objects via 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 StageController.update().

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

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

    Step 12: Newton’s Law of Gravitation

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

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

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

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

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

    Step 13: Revising Math Concepts

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

    frameWork

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

    We should revise a few concepts:

    • Flash works in radians rather than degrees.
    • Flash’s coordinate system has its y-axis reversed: going down means an increase in y.
    • We can get the angle of the line connecting A to B using Math.atan2(B.y - A.y, B.x - A.x).
    • We can use trigonometry to figure out how much we need to move B along each axis, based on this angle and the force:
      • B.x += (Force*Math.cos(angle));
      • B.y += (Force*Math.sin(angle));
    • We can use 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 StageController – but before that, we will need to use a Boolean function to toggle between the two functions:

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

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

    Inside KeyDownHandler():

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

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

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

    Step 16: Modification

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

    I’d like to alter the formula like so:

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

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

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


    Step 17: The Text Class

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

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

    
    
    package
    {
    	import flash.display.MovieClip;
    	import flash.text.TextField;
    	import flash.events.Event;
    	import flash.text.TextFormat;
    
    	import flash.text.TextFormatAlign;
    
    	public class Text extends MovieClip
    	{
    		public var _scoreText:TextField= new TextField();
    
    		public function Text(string:String)
    		{
    			var myScoreFormat:TextFormat = new TextFormat(); //Format changeable
    			myScoreFormat.size = 24;		
    
    			myScoreFormat.align = TextFormatAlign.LEFT;
    			myScoreFormat.color = (0x131313);
    
    			_scoreText.defaultTextFormat = myScoreFormat;
    
    			_scoreText.text = string;
    
    			addChild(_scoreText);
    		}
    
    		public function updateText(string:String)
    		{
    			_scoreText.text = string;
    		}
    	}
    }
    

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


    Step 18: Adding Power for Player

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

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

    Declare these variables within the Ship class:

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

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

    
    
    addEventListener(Event.ENTER_FRAME, updatePower);
    

    Here’s the actual updatePower() function:

    
    
    	private function updatePower(e:Event):void
    		{
    			// add a new text object if it doesn't already exist
    			if (!powerText) {
    				powerText = new Text(String(int(totalPower)));
    				addChild(powerText);
    				powerText.x -= 20;			//Adjust position
    				powerText.y -= 16;
    			}
    
    			// fps = 24, so this makes power decrease by 1/sec
    			totalPower -= 1 / 24;
    			powerText.updateText(String(int(totalPower)));
    		}
    

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


    Step 19: Make Energy Increase Power

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

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

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

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


    Step 20: Setting Up the Score

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

    Here, we will need three more variables:

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

    Declare these in StageController class:

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

    In the constructor, add this code:

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

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

    
    
    score.updateText(String(totalScore));
    

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

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


    Extra Features and Polishing

    Space Background

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

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

    Now create the Star class:

    
    
    package assets
    {
    	import flash.display.MovieClip;
    	import flash.events.Event;
    
    	public class Star extends MovieClip
    	{
    		private var speed:Number;
    
    		public function Star(alpha:Number, size:Number, speed1:Number)
    		{
    			graphics.beginFill(0xCCCCCC);
    			graphics.drawCircle(0, 0, size);
    
    			this.addEventListener(Event.ENTER_FRAME, moveDown);
    			speed = speed1;
    		}
    
    		private function moveDown(e:Event):void
    		{
    			this.y += speed;
    
    			if (this.y >= 600) {
    				this.y = 0;
    			}
    		}
    	}
    }
    

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

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

    Here’s the actual createStars() function:

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

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

    Range indicator

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

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

    
    
    			graphics.beginFill(0xCCCCCC, 0.1);
    

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


    Conclusion

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

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


  3. Matt Stuttard Parker says:
    June 25, 2012 at 6:06 am

    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!


  4. Kah Shiu Chong says:
    June 25, 2012 at 6:55 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.


  5. Porter says:
    June 25, 2012 at 7:52 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?


  6. Sebastian Bratu says:
    June 25, 2012 at 8:48 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.


  7. Kah Shiu Chong says:
    June 25, 2012 at 9:32 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!)


  8. Collis says:
    June 25, 2012 at 10:24 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!!


  9. Porter says:
    June 25, 2012 at 11:17 am

    Kongregate is one of the largest Flash game portals on the net, and has its own API that can be integrated into your games (for which Kongregate even rewards you financially). In this tutorial, I’ll show you how to implement the Kongregate API into your games, and also go into detail about what the API is capable of and why you should use it.

    (Note that this tutorial assumes you already have a Kongregate account; if you don’t, then please create one now.)


    Final Result Preview

    Let’s take a look at what the API enables us to do:

    Badges

    Mass Messages

    High Scores

    There’s another big reason to implement the API…


    Step 1: Let’s Get Motivated

    Before we dive into the technical aspects of implementing the Kongregate API, let’s get ourselves hyped up a little bit, and make sure that we actually want to implement it.

    There are many reasons to implement the API, but to most developers, nothing speaks louder than money, and there’s plenty of that involved. When you upload your game to Kongregate, you automatically earn 25% of all ad revenue generated by your game’s page.

    It gets better; if you implement their “Statistics & Challenges API”, you’ll receive an additional 10%! Finally, if your game is exclusive to Kongregate, or sponsored by them, you receive an additional 15%. This gives you the opportunity to earn up to 50% of the ad revenue for your game on Kongregate. If you’re wondering how much that is, check out some of my personal stats:


    Step 2: Setting Up Our Work Environment

    For this tutorial, we’ll be using FlashDevelop, a free (and amazing) open source editor for developers. We’ll be doing everything in simple .as files, so if you’d like to follow along using the Flash IDE, you shouldn’t have any trouble. If you’d like to use FlashDevelop and are unfamiliar with it, check out this excellent FlashDevelop beginner guide to get you started on what I would consider the best AS3 editor out there.

    To begin, open FlashDevelop, go to the Project tab, and select “New Project”. From here, select “AS3 Project with Pre-Loader”. Alternatively, you can grab the Preloader.as and Main.as files from the source download, and simply follow along.

    Your file should be a barebones Main.as file, like this:

    
    
    package {
    	import flash.display.Sprite;
    	import flash.events.Event;
    
    	/**
    	 * ...
    	 * @author Your Name
    	 */
    
    	[Frame(factoryClass = "Preloader")]
    
    	public class Main extends Sprite {
    
    		public function Main():void {
    			if (stage) init();
    			else addEventListener(Event.ADDED_TO_STAGE, init);
    		}
    
    		private function init(e:Event = null):void {
    			removeEventListener(Event.ADDED_TO_STAGE, init);
    			// entry point
    		}
    
    	}
    
    }
    

    Nothing above should be new to you; if it is, all you need to know is that this file is the entry point for our program, this is where it all begins. If you compile this with FlashDevelop, you should get a blank white screen, with no compiler errors.


    Step 3: Let’s Get Connected

    Before we dive into all the cool features of the API, we need to make sure that we have the API up and running.

    Unlike many sponsor APIs, the Kongregate API isn’t a standalone set of files that we need to compile with our project. The API is actually stored on the Kongregate server, and we load it in at runtime. There’s a number of ways to do this in your projects, but for the sake of this tutorial, we’ll simply connect within our Main.as, and a save a reference to it there.

    To start, copy the following code into our Main.as file just below the existing imports:

    
    
    import flash.display.LoaderInfo;
    import flash.display.Loader;
    import flash.net.URLRequest;
    import flash.events.Event;
    import flash.system.Security;
    

    The above are just a few simple imports that will allow us to use the necessary classes for loading in the Kongregate API.

    Next, we’ll add a variable to store our reference to the Kongregate API. Go ahead and add the following right above the constructor of our Main.as file.

    
    
    private var kongregate:*;
    

    Notice that the data type of our kongregate variable is *. If you’re unfamiliar with this, we’re simply telling the compiler that the kongregate variable will accept any data type, much like a wild card.

    (Also, note that in a real game you’d want to store your reference to the API somewhere that your entire project has access to, such as a public static const. This reference is needed so that you can use the API from anywhere in your project, for any purpose, rather than just in the Main.as file when we first start up.)

    This next piece of code will be contained in a custom function by the name of initKongregateAPI(). This isn’t actually necessary, but I prefer to encapsulate ideas when writing code, as it helps keep the code readable and easy to work with.

    Go ahead and add this function below the init function in Main.as.

    
    
    private function initKongregateAPI():void {
    	// Pull the API path from the FlashVars
    	var paramObj:Object = LoaderInfo(root.loaderInfo).parameters;
    
    	// The API path. The "shadow" API will load if testing locally.
    	var apiPath:String = paramObj.kongregate_api_path ||
    	"http://www.kongregate.com/flash/API_AS3_Local.swf&quot;;
    
    	// Allow the API access to this SWF
    	Security.allowDomain(apiPath);
    
    	// Load the API
    	var request:URLRequest = new URLRequest(apiPath);
    	var loader:Loader = new Loader();
    	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
    	loader.load(request);
    	this.addChild(loader);
    }
    

    While that may look like a lot of code, it’s really not much, and with the comments, it’s quite easy to follow.

    As you’ll see, in the first part we’re creating a variable to store the API path from the FlashVars (if you don’t know what these are, look them up really quick, they’re a great thing to understand).

    In the second chunk, we determine whether the SWF is on the Kongregate website or running locally, and we assign the proper information to the apiPath variable.

    Next, we give the API access to the SWF, with a simple security.allowDomain call, where we pass in the apiPath as the parameter.

    We then create a new URLRequest object, which gets the apiPath passed in to the constructor, a new Loader object, and add an event listener for the loader which will call loadComplete when done.

    Last, we call loader.load and pass in our request (the newly created URLRequest object, which contains the apiPath of the Kongregate API). If you understand what just happened, great; if not, don’t sweat it, as you won’t have to touch this again.

    Don’t Forget to Call It!

    Now that the initKongregateAPI function is created, and contains all of the connection code, we should probably make sure this function actually gets called! Simply go back to the init function that our Main.as file already contained, and add a function call to initKongregateAPI after the line that “entry point” line, like so,

    
    
    private function init(e:Event = null):void {
    	removeEventListener(Event.ADDED_TO_STAGE, init);
    	// entry point
    
    	initKongregateAPI();
    }
    

    Finally, we need to add that loadComplete function, to be called when the COMPLETE event is fired from our previous code. Add this function below the initKongregateAPI function in Main.as.

    
    
    // This function is called when loading is complete
    private function loadComplete(event:Event):void {
    	// Save Kongregate API reference
    	kongregate = event.target.content;
    
    	// Connect to the back-end
    	kongregate.services.connect();
    
    	// You can now access the API via:
    	// kongregate.services
    	// kongregate.user
    	// kongregate.scores
    	// kongregate.stats
    	// etc...
    }
    

    The above code is super simple; let’s go over it. We start off by saving a reference to the Kongregate API. As you can see, we’re referencing the Kongregate API through the passed in event parameter, via event.target.content – simple enough.

    Now all we have to do is connect, and our SWF is good to go. As you can see, we connect by calling the kongregate.services.connect method. No arguments required.

    While that may have seemed like a lot of work, it really wasn’t. I simply went over the connection process in a lot of detail, so that you can understand how we’re actually gaining access to the API, rather than just having that access and using it. Now that you understand it, you can use all the above as boilerplate code.


    Step 4: The Statistics & Challenges API

    Now that we’re connected, we can take a look at the most important feature of the entire API: the Statistics & Challenges portion. This API sends player related stats to the Kongregate server, which enables a number of things.

    First off, this is the most basic way to allow users to compete for high scores on Kongregate. With the API integrated, the Kongregate side bar will include a new tab labeled “ACHIEVEMENTS”, which can be found next to the “CHAT” tab. Players can view leaderboards for any stat you send to the servers, which could be anything from a basic high score to the total number of enemies defeated.

    The second and far more important use, is to allow Kongregate to use the stats you submit to create “badges” for your games. Badges are a central part of the Kongregate user experience, and are much like the achievement systems on platforms such as Xbox LIVE.

    The best part about having badges added to your game is that your game will become featured for a short duration, greatly increasing the number of views you get, and thus greatly increasing your ad revenue. Even after your game is out of the spotlight, all badged games on Kongregate continue to receive increased views over normal games, which gives you an excellent long tail revenue stream.

    Note that badges aren’t added by developers, but are instead created by the Kongregate staff. You’ll need a high rated game to get selected, but you’ll also need the API to be set up – so let’s get that half the battle out of the way!


    Step 5: Back-End Preparation

    To actually use the stats that we’ll be sending, Kongregate first requires us to let their server know what information it should be prepared to receive from us.

    To do this, we simply go to the Statistics page for our game on the Kongregate website. This can be found in the “Edit Game” page, or by adding /statistics to the end of your game’s URL (for example, http://www.kongregate.com/games/EpicShadow/pixel-purge/statistics). For this tutorial, we’ll simply upload our test SWF as the “game”.

    Before adding any stats to the Statistics & Challenges API, we need to first understand the four types of stats that can be used, and the rules that they are bound to. Values must be positive, and must be whole integers. The four types are as follows:

    • Max: The value on the server will be replaced if the new value is higher than the stored value. For example, a high score of 152,000 would replace an old high score of 120,000.
    • Min: The value on the server will be replaced if the new value is lower than the stored value. For example, in a racing game, a lap time of 31 seconds would replace an older value of 35.
    • Add: The new value will be added to the stored value. A common use of this would be total enemies defeated, player deaths, etc. Too many requests to the server may result in inaccurate data, so it’s advised that data is only sent in bulk, such as when a level is completed or when the player dies.
    • Replace: The new value will replace the stored value no matter what. This can be used for a number of things, such as average survival time or player ranking.

    Knowing which of the above types you need to use for each of your game stats is extremely important, so make sure you familiarize yourself with the above list. You’ll obviously want a list of stats that you want your game to send to Kongregate, so make sure that you have those prepared before you dive into the next step when actually submitting a game.

    For the sake of this tutorial, we’ll simply use the following stats:

    • Total Clicks (Add)
    • Max Clicks (Max)
    • Last X (Replace)

    Once your list is prepared, head to the Statistics page of your game, and input the required data. Once the back-end work is done on the Statistics page, the game will be ready to submit data to the Kongregate server.


    Step 6: How to Send Stats

    To actually send data to the server, we simply call the “submit” function, which looks like this:

    
    
    submit(statName:String, value:Number):void
    

    As you can see, the function takes two parameters:

    • statName is the name of your stat. It’s very important that the String passed is identical (case sensitive) to the name of the stat you listed in the previous step when prepping the server to handle your stats.
    • value is the actual numeric value to be passed. Even though the data type is Number, remember that your value must be a positive, whole integer.

    To call this function in your game, simply do the following:

    
    
    kongregate.stats.submit(“Your Stat String”, statValue);
    //stat value could be 1, 500, 5342324, etc.
    

    Even though we had four different types of stats we could send, this function only sends the value; the server itself will look at the information we provided in the previous step to determine how to treat the incoming data. It’s as simple as that; now we know how to send data to the server.


    Step 7: Prepping Our Project to Send Stats

    Now that we’ve prepped the back-end on the Kongregate website, and we now know how to send data, let’s give this project a go.

    The first thing we need to do is add some code to our project to actually send our stats. Since the easiest thing to track is mouse input, I’ve chosen mouse-related stats. As you saw in our previous step, I chose Max Clicks, Total Clicks, and Last X.

    Max Clicks will be the high score for how many times we click in a single game, to demonstrate the Max type; Total Clicks will be the grand total of all clicks we’ve done, to demonstrate the Add type; and Last X will be the x-position of our most recent click, to demonstrate the Replace type.

    To track our Mouse clicks, we’ll need import the MouseEvent class. Go back to Main.as, and add the following to your imports:

    
    
    import flash.events.MouseEvent;
    

    Now we’re going to need to add a variable for our Max Clicks stat, to keep track of the total number of clicks per game session. Right below where we added the kongregate reference variable (of data type *), add the following:

    
    
    private var maxClicks:int;
    

    We’re going to need an Event Listener to listen for our clicks, so we’ll add that now. In the init function, right below the call to initKongregateAPI, add the following:

    
    
    //Event listener for mouse clicks
    stage.addEventListener(MouseEvent.CLICK, clicked);
    

    As you can see in the above code, the function called whenever the event it fired is called clicked. Let’s go ahead and create that function. Add the following below your loadComplete function:

    
    
    private function clicked(event:Event):void {
    	maxClicks++;
    	kongregate.stats.submit("Total Clicks", 1);
    	kongregate.stats.submit("Max Clicks", maxClicks);
    	kongregate.stats.submit("Last X", mouseX);
    }
    

    All we’re doing here is incrementing the maxClicks variable by 1, and then submitting all the required information to the Kongregate server. This will add 1 to the Total Clicks stat, send the current maxClicks variable to the server, which will then determine if it’s higher than the previous value and replace it if so, and send the x-position of our previous click, which will automatically replace the previous value.

    Our SWF may just be a blank screen, but a lot is going on, and we’re about to see it in action. Make sure you compile the project before moving on.


    Step 8: Testing Our Project

    Now it’s time to actually upload our project, and see it in action.

    Go back to the Kongregate website, head to your game page, and upload the final version of our project. Once you’ve uploaded the project, you’ll be brought to a preview screen, where we can test our project before publishing it. To save the Kongregate staff a lot of time and energy, do everyone a favor and do not press publish on your test SWF. (If you’re working on a real game, go ahead, but for the sake of this tutorial we will not be publishing this project.)

    Once you’re on the test page, give the game a few clicks. Refresh the page, and you should now see that there is a “HIGH SCORES” tab next to the “CHAT” and “GAME” tab. If you’ve done everything correctly up to this point, you should have a drop down box that currently reads “Last X” that also contains “Max Clicks” and “Total Clicks”. Note that clicking quickly will result in innacurate stats, as the server can’t keep up with all the requests, so click slowly for best results. This is why I advised earlier that you send large batches of data upon death, or level completion, when possible.

    Well, there you go: you’ve now got the most important portion of the Kongregate API up and running. If your project isn’t working at this point, make sure that your Kongregate back-end stat names are typed exactly as they are in your submit function – case-sensitive – as that’s usually the problem.

    You can also find the completed code in the final files folder in the source download, so compare your code to that if you’re still having issues.


    Step 9: Mass Message Communications

    Ever released a game, then later, really wanted to reach out to all of your fans? Well, with the Kongregate API, you can do just that – at least, for all of your Kongregate fans.

    There are some restrictions on who can do this, but these restrictions are very much in the best interest of both developers and players. In order to qualify, your game must receive a 3.75 rating or higher, and have at least 10k gameplays.

    You can send an “active players” message at most once every seven days. These messages will be sent to any players who have played the game at least three times ever, and at least once within the last ten days.

    You can send an “inactive players” message at most once every 30 days. These messages will be received by any players who have played at least five times total, but not within the last ten days.

    There are many of reasons to send these messages to your players, such as alerting them of bug fixes, or perhaps informing them of an upcoming sequel. Regardless of what you use this for, it’s an incredibly useful system that can really help you leverage your fans.

    For more information, see this guide.


    So Much More…

    While we’ve covered a lot in this tutorial, the Kongregate API is capable of doing much more. Unfortuantely, I’d have to write a small book to go over all of the features, especially those that are useful for web based MMOs. If you’re interested in checking out what other features the API has to offer, I recommend checking out the Kongregate Developers Center for more.

    Now that you know how to get the Kongregate API up and running, I strongly encourage you to add it to all of your future games; if you’re lucky, you might even get some badges, and that’s when the real fun begins.


  10. Matt Stuttard Parker says:
    June 25, 2012 at 11:59 am

    Last year, we released Tr.ace(), an open source debugging tool for Flash that expanded on the built-in trace() function. Now, Tr.ace() v2.0 introduces several new features including the much requested “textfield console” to help you squash those bugs once and for all!


    New to Tr.ace()?

    Tr.ace() was released nearly a year ago as an Exclusive Freebie on Activetuts+ and is an open source debugging utility for Flash that allowed you to restrict the traces shown within your application to particular users or classes or even both. You could also add linebreaks, timestamps and trace nested arrays and objects neatly with one line of code!

    Let’s take a look at what’s changed since Tr.ace() was first released…


    By Popular Demand: Tr.ace() Console

    The Tr.ace() library now features a class named TrConsole which provides you with a basic console within your SWF through which you can view all your Tr.ace() traces! Check out the demo below to see it in action:

    You can clear the console, copy the output to the clipboard and save the output to a text file. You can also minimize the console to reduce the space taken up on screen as well as move it around the screen by simply dragging it. It’s also fully resizable!

    To take advantage of this feature you only need two lines of code:

    
    
    // create the TrConsole instance and add it to the stage
    var console:TRConsole = new TrConsole();
    addChild(console);

    And that’s it – easy!

    There are also a few extra options for you to tailor the colours of the console and whether autoscroll is enabled or not. Check out the documentation and example files for more info.


    Optional Username and Class Parameters

    When Tr.ace() was intially released the username and class parameters were required for all trace calls whether you wanted to use them or not. You’ll be happy to know that they are now optional!

    This does reduce some of the functionality of the library but if you’re just wanting to see your traces via the console then you’re able to, without the bloat of the rest of the library.

    With parameters:

    
    
    Tr.ace("with parameters", TrUsers.MSFX, ClassName);

    Without parameters:

    
    
    Tr.ace("without parameters!");

    This will hopefully make the library more accessible and less “verbose” for tracers everywhere.


    Clear, Copy and Save Your Traces

    Via the console featured above you can clear, copy to clipboard, and save the current trace log.

    For those who aren’t using the console you can also achieve these via calls to the Tr class as shown below:

    
    
    // to clear the trace log
    Tr.clearLog();
    
    // to copy to the clipboard
    Tr.copyLogToClipboard();
    
    // to save the log as a text file with timestamp
    Tr.saveLog();

    The clipboard functionality must be triggered via a user interaction, as detailed here.


    Downloading Tr.ace()

    Tr.ace() is an open source library that is available to download here at Activetuts+ in ZIP format and is also available as a public repository on my GitHub, for those a little more nerdy or who wish to fork and/or contribute towards the Tr.ace() library.

    The library is AS3 only and has two separate repositories developed for both Flash Player 9 and Flash Player 10+

    To use the Tr.ace() library you must download one of the above source packages and copy and paste the ‘uk’ directory, located within the ‘src’ directory, into your global classpath directory. You’re then all set to go!


    Documentation for Tr.ace()

    Within the download package you’ll find a ‘docs’ directory; open the index.html file to view the ASDocs-generated documentation for Tr.ace(). You can also find the documentation online: http://docs.msfx.co.uk/as3/trace/.


    Happy Tracing!

    So, that’s it really. If you have any questions or suggestions for the library feel free to get in touch in the comments.

    Happy tracing!


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
May 2013
M T W T F S S
« Jul    
 12345
6789101112
13141516171819
20212223242526
2728293031  
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