logo
468x60-2-495


  • Home
  • Privacy Policy
  • About
search
top
Dec 9, 2011 Posted on Dec 9, 2011 in Hints and Tips | 10 comments

Build a Dynamic Flash Game Menu: Slides

Stop using static menus! Most players immediately base their initial impression of a Flash game on the menu that they see when they load it. Stand out from the crowd with a dynamic menu!


Final Result Preview

Introduction: Static to Dynamic

The word “static” essentially means lacking in change. The majority of menus we see throughout web games are lacking in change, you simply press Play and the game starts. Menus like that are overused and show little creativity or innovation.

To make a menu “dynamic” we must continuously cause change. So in this tutorial that is exactly what we are going to accomplish: a menu that continuously changes.


Step 1: Setting Up

The first thing we are going to need to create is a new Flash File (ActionScript 3.0). Set its width to 650px, its height to 350px, and the frames per second to 60. The background color can be left as white.

Now save the file; you can name it whatever you please, but I named mine menuSlides.fla.

In the next section we will create the nine MovieClips used in the menu. For reference, here is a list of all the colors used throughout the tutorial:

  • White – #FFFFFF
  • Gold – #E8A317
  • Light Gold – #FBB917
  • Blue – #1569C7
  • Light Blue – #1389FF
  • Green – #347235
  • Light Green – #3E8F1B
  • Red – #990000
  • Light Red – #C10202
  • Matte Grey – #222222

Step 2: Creating the Slide MovieClips

To start with we will create the slides used in the transitions, but before we begin let’s turn on some very useful Flash features.

Right-Click the stage and select Grid > Show Grid. By default it will create a 10px by 10px grid across the stage. Next, right-click the stage again and this time select Snapping > Snap to Grid.

Now we can begin drawing! Select the Rectangle Tool and draw a Light Gold rectangle, 650px wide and 350px tall (you can Alt-click on the stage to make this easier). Now change the color to Gold and draw groups of three squares, each 20x20px, to form the shape of an L in each corner,:

The basic Slide Design

Select the whole stage, right-click and choose Convert to Symbol. Name the MovieClip goldSlide and make sure that the type is MovieClip and the registration is top-left.

To save time and make things a whole lot easier, right-click the goldSlide MovieClip in the Library and select Duplicate Symbol three times to make three more copies. Change the colors in the new MovieClips to blue, green and red, then rename the MovieClips to blueSlide, greenSlide and redSlide.

Before we continue we should add some text to each slide. On goldSlide write PLAY, on blueSlide write INSTRUCTIONS, on greenSlide write OPTIONS and on redSlide write CREDITS.

Now that we have the text in place we can break it apart by right-clicking on it and selecting Break Apart twice; this will break the text down to a fill which will transition more smoothly. Plus as a bonus there will be no need to embed a font if you are just using it for the menu!

The Buttons

Now that we have drawn the 4 slides we can focus on the sideButton MovieClip that is used to move the slides either left or right.

First, draw a rectangle 30x60px with only a stroke (no fill), then draw diagonal lines 45 degrees from the top-right and bottom-right corners until they snap together in the middle of the opposite side. Now apply a Matte Grey fill to the triangle:

What your side Button Should Look Like

Next, delete the lines, then right-click the triangle and select Convert to Symbol. Name it sideButton, set the type to Button and make sure the registration is in the top-left corner.

Now insert 3 keyframes in the timeline by right-clicking the timeline and selecting Insert Keyframe. On the Up frame, select the fill of the triangle, go to the Windows tab and select Color. Change the Alpha to 50%. On the Over Frame repeat the same process, but this time set the alpha to 75%.

Now we can begin on the four numbered circle buttons, for jumping directly to a particular slide.

To start draw a white 30px circle with no stroke. Convert it to a symbol, name it circleOne, and set its type to Button and its registration point to the center. Insert three keyframes like we did before and then go to the Up frame.

Draw a black 25px circle with no stroke and center it to the middle through the coordinates or by using the Align menu. Next deselect the black circle, then reselect it and delete it. You should now have a white ring remaining. Now grab the text tool and put a white “1″ in the center of the ring. Then break this number apart until it is a fill.

circleOne Up Frame

Go to the Over frame and draw a black “1″. Center it and break it apart until it becomes a fill. Now deselect and reselect the fill, then delete it. Select everything on the frame and copy it, then go to the Down frame, select everything on it and hit delete. Paste in what we have copied.

circleOne Over Frame

Now create three more circle MovieClips, following the same process, for the numbers 2, 3 and 4.


Step 3: Positioning the MovieClips

Okay, we’re almost half-way done! First drag all of the slides onto the stage and position them with the following coordinates:

  • goldSlide: (0, 0)
  • blueSlide: (650, 0)
  • greenSlide: (1300, 0)
  • redSlide: (1950, 0)

Now drag and drop two copies of the sideButton. The first copy should be positioned at (10,145); before we can position the second copy we must first flip it!

Select the second copy and press Ctrl-T. Change the left-right to -100% and leave the up-down at 100%. Now move the second copy to (640,145).

Finally drag and drop the four circle MovieClips and position them as so:

  • circleOne: (30, 320)
  • circleTwo: (70, 320)
  • circleThree: (110, 320)
  • circleFour: (150, 320)

Your stage should now look like this:

What your stage Should Look Like

The blue, green and red slides are hidden just off to the right of the stage. Now select everything on the stage and convert to a symbol. Name it menuSlidesMC, set the type to MovieClip and the registration to the top-left corner, and export it for ActionScript as MenuSlidesMC.

Before we finish we must give each of the MovieClips inside menuSlidesMC an instance name. Select each slide in the order they appear from the left and name them slide1, slide2, slide3 and slide4 respectively. Name the circle buttons one, two, three and four, and finally name the side buttons left and right.


Step 4: Setting Up the Classes

Now that all of our MovieClips have been created we can start setting up the two classes we are going to use.

First go to your Flash file’s Properties and set its class to menuSlides; then, create a new ActionScript 3.0 file and save it as menuSlides.as.

Now copy the following code into it; I will explain it after:

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

	public class menuSlides extends MovieClip{
		public var menuSlidesMC:MenuSlidesMC = new MenuSlidesMC();
		public function menuSlides(){
			addChild(menuSlidesMC);
		}
	}
}

Pretty basic – it’s a document class, into which we imported the MovieClips and Events we will use. Then we created an instance of MenuSlidesMC, and added it to the stage.

Now create a new ActionScript 3.0 file for the menuSlidesMC instance. Save it as MenuSlidesMC.as and copy the following code into it:

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

	public class MenuSlidesMC extends MovieClip{
		public var speed:Number = new Number();
		public var activeSlide:Number = new Number();
		public function MenuSlidesMC(){
			speed = 10;
			activeSlide = 1;
			addEventListener(MouseEvent.CLICK, slidesClick);
			addEventListener(Event.ENTER_FRAME, slidesMove);
		}
	}
}

Just like last time, we imported what we are going to need, but we created two number variables. The first variable, speed, is actually how many pixels the slides are moved by each frame. (Note: this number has to evenly divide into your stage’s width to give a smooth transition). The second variable, activeSlide, tells us which slide is currently set to be on screen.

We also added two event listeners for functions we are going to create; one of them is called on a mouse click, and the other is called at the beginning of every frame.


Step 5: Creating the Event Handler Functions

To begin we will get the mouse click function out of the way. Start by creating a public function named slidesClick():

public function slidesClick(event:MouseEvent):void {

}

Next we will create some if-statements regarding the event.target.name. Basically, this property stores the name of the object that was targeted by the mouse click. We can use this to check which button is pressed:

if(event.target.name == "left"){
	if(activeSlide>1){
		activeSlide-=1;
	}
}else if(event.target.name == "right"){
	if(activeSlide<4){
		activeSlide+=1;
	}
}

if(event.target.name == "one"){
	activeSlide=1;
}else if(event.target.name == "two"){
	activeSlide=2;
}if(event.target.name == "three"){
	activeSlide=3;
}else if(event.target.name == "four"){
	activeSlide=4;
}

The code above goes in the slidesClick() function. The first set of if-statements are for the left and right side buttons; they increase or decrease the value of activeSlide, but never allow the value to become less than 1 or greater than 4 (since we only have four slides). The second set of if-statements are for the circle buttons; instead of just incrementing or decrementing the value of activeSlide they set it to the selected value.

Now let’s begin with the ENTER_FRAME handler function:

public function slidesMove(event:Event):void {

}

Add the slidesMove() function below your slidesClick() function and we’ll start adding some code to it. First, we’ll use a switch to check which slide should be on the screen, based on the value of activeSlide:

switch (activeSlide){
case 1:

break;
case 2:

break;
case 3:

break;
case 4:

break;
}

Now in each case we will create an if/else block that will check that slide’s current x-position, and move all of the slides either left, right, or not at all, depending on where the desired slide currently sits.

The first case looks like this:

if(slide1.x<0){
	slide1.x+=speed;
	slide2.x+=speed;
	slide3.x+=speed;
	slide4.x+=speed;
}else if(slide1.x>0){
	slide1.x-=speed;
	slide2.x-=speed;
	slide3.x-=speed;
	slide4.x-=speed;
}

Now all we have to do is repeat the same process for the other cases! After you are done your swtich should look like this:

switch (activeSlide){
	case 1:
		if(slide1.x<0){
			slide1.x+=speed;
			slide2.x+=speed;
			slide3.x+=speed;
			slide4.x+=speed;
		}else if(slide1.x>0){
			slide1.x-=speed;
			slide2.x-=speed;
			slide3.x-=speed;
			slide4.x-=speed;
		}
	break;
	case 2:
		if(slide2.x<0){
			slide1.x+=speed;
			slide2.x+=speed;
			slide3.x+=speed;
			slide4.x+=speed;
		}else if(slide2.x>0){
			slide1.x-=speed;
			slide2.x-=speed;
			slide3.x-=speed;
			slide4.x-=speed;
		}
	break;
	case 3:
		if(slide3.x<0){
			slide1.x+=speed;
			slide2.x+=speed;
			slide3.x+=speed;
			slide4.x+=speed;
		}else if(slide3.x>0){
			slide1.x-=speed;
			slide2.x-=speed;
			slide3.x-=speed;
			slide4.x-=speed;
		}
	break;
	case 4:
		if(slide4.x<0){
			slide1.x+=speed;
			slide2.x+=speed;
			slide3.x+=speed;
			slide4.x+=speed;
		}else if(slide4.x>0){
			slide1.x-=speed;
			slide2.x-=speed;
			slide3.x-=speed;
			slide4.x-=speed;
		}
	break;
}

And that’s it! We are all finished with the code and the menu should be working great right now.


Conclusion

Thank you for taking the time to read through the tutorial, I hope it was helpful and that you learned a little something about dynamic menus.



View full post on Activetuts+

banner ad

10 Responses to “Build a Dynamic Flash Game Menu: Slides”

  1. Tyler Seitz says:
    December 9, 2011 at 9:39 pm

    Stop using static menus! Most players immediately base their initial impression of a Flash game on the menu that they see when they load it. Stand out from the crowd with a dynamic menu!


    Final Result Preview

    Introduction: Static to Dynamic

    The word “static” essentially means lacking in change. The majority of menus we see throughout web games are lacking in change, you simply press Play and the game starts. Menus like that are overused and show little creativity or innovation.

    To make a menu “dynamic” we must continuously cause change. So in this tutorial that is exactly what we are going to accomplish: a menu that continuously changes.


    Step 1: Setting Up

    The first thing we are going to need to create is a new Flash File (ActionScript 3.0). Set its width to 650px, its height to 350px, and the frames per second to 60. The background color can be left as white.

    Now save the file; you can name it whatever you please, but I named mine menuSlides.fla.

    In the next section we will create the nine MovieClips used in the menu. For reference, here is a list of all the colors used throughout the tutorial:

    • White – #FFFFFF
    • Gold – #E8A317
    • Light Gold – #FBB917
    • Blue – #1569C7
    • Light Blue – #1389FF
    • Green – #347235
    • Light Green – #3E8F1B
    • Red – #990000
    • Light Red – #C10202
    • Matte Grey – #222222

    Step 2: Creating the Slide MovieClips

    To start with we will create the slides used in the transitions, but before we begin let’s turn on some very useful Flash features.

    Right-Click the stage and select Grid > Show Grid. By default it will create a 10px by 10px grid across the stage. Next, right-click the stage again and this time select Snapping > Snap to Grid.

    Now we can begin drawing! Select the Rectangle Tool and draw a Light Gold rectangle, 650px wide and 350px tall (you can Alt-click on the stage to make this easier). Now change the color to Gold and draw groups of three squares, each 20x20px, to form the shape of an L in each corner,:

    The basic Slide Design

    Select the whole stage, right-click and choose Convert to Symbol. Name the MovieClip goldSlide and make sure that the type is MovieClip and the registration is top-left.

    To save time and make things a whole lot easier, right-click the goldSlide MovieClip in the Library and select Duplicate Symbol three times to make three more copies. Change the colors in the new MovieClips to blue, green and red, then rename the MovieClips to blueSlide, greenSlide and redSlide.

    Before we continue we should add some text to each slide. On goldSlide write PLAY, on blueSlide write INSTRUCTIONS, on greenSlide write OPTIONS and on redSlide write CREDITS.

    Now that we have the text in place we can break it apart by right-clicking on it and selecting Break Apart twice; this will break the text down to a fill which will transition more smoothly. Plus as a bonus there will be no need to embed a font if you are just using it for the menu!

    The Buttons

    Now that we have drawn the 4 slides we can focus on the sideButton MovieClip that is used to move the slides either left or right.

    First, draw a rectangle 30x60px with only a stroke (no fill), then draw diagonal lines 45 degrees from the top-right and bottom-right corners until they snap together in the middle of the opposite side. Now apply a Matte Grey fill to the triangle:

    What your side Button Should Look Like

    Next, delete the lines, then right-click the triangle and select Convert to Symbol. Name it sideButton, set the type to Button and make sure the registration is in the top-left corner.

    Now insert 3 keyframes in the timeline by right-clicking the timeline and selecting Insert Keyframe. On the Up frame, select the fill of the triangle, go to the Windows tab and select Color. Change the Alpha to 50%. On the Over Frame repeat the same process, but this time set the alpha to 75%.

    Now we can begin on the four numbered circle buttons, for jumping directly to a particular slide.

    To start draw a white 30px circle with no stroke. Convert it to a symbol, name it circleOne, and set its type to Button and its registration point to the center. Insert three keyframes like we did before and then go to the Up frame.

    Draw a black 25px circle with no stroke and center it to the middle through the coordinates or by using the Align menu. Next deselect the black circle, then reselect it and delete it. You should now have a white ring remaining. Now grab the text tool and put a white “1″ in the center of the ring. Then break this number apart until it is a fill.

    circleOne Up Frame

    Go to the Over frame and draw a black “1″. Center it and break it apart until it becomes a fill. Now deselect and reselect the fill, then delete it. Select everything on the frame and copy it, then go to the Down frame, select everything on it and hit delete. Paste in what we have copied.

    circleOne Over Frame

    Now create three more circle MovieClips, following the same process, for the numbers 2, 3 and 4.


    Step 3: Positioning the MovieClips

    Okay, we’re almost half-way done! First drag all of the slides onto the stage and position them with the following coordinates:

    • goldSlide: (0, 0)
    • blueSlide: (650, 0)
    • greenSlide: (1300, 0)
    • redSlide: (1950, 0)

    Now drag and drop two copies of the sideButton. The first copy should be positioned at (10,145); before we can position the second copy we must first flip it!

    Select the second copy and press Ctrl-T. Change the left-right to -100% and leave the up-down at 100%. Now move the second copy to (640,145).

    Finally drag and drop the four circle MovieClips and position them as so:

    • circleOne: (30, 320)
    • circleTwo: (70, 320)
    • circleThree: (110, 320)
    • circleFour: (150, 320)

    Your stage should now look like this:

    What your stage Should Look Like

    The blue, green and red slides are hidden just off to the right of the stage. Now select everything on the stage and convert to a symbol. Name it menuSlidesMC, set the type to MovieClip and the registration to the top-left corner, and export it for ActionScript as MenuSlidesMC.

    Before we finish we must give each of the MovieClips inside menuSlidesMC an instance name. Select each slide in the order they appear from the left and name them slide1, slide2, slide3 and slide4 respectively. Name the circle buttons one, two, three and four, and finally name the side buttons left and right.


    Step 4: Setting Up the Classes

    Now that all of our MovieClips have been created we can start setting up the two classes we are going to use.

    First go to your Flash file’s Properties and set its class to menuSlides; then, create a new ActionScript 3.0 file and save it as menuSlides.as.

    Now copy the following code into it; I will explain it after:

    
    
    package{
    	import flash.display.MovieClip;
    	import flash.events.Event;
    	import flash.events.MouseEvent;
    
    	public class menuSlides extends MovieClip{
    		public var menuSlidesMC:MenuSlidesMC = new MenuSlidesMC();
    		public function menuSlides(){
    			addChild(menuSlidesMC);
    		}
    	}
    }
    

    Pretty basic – it’s a document class, into which we imported the MovieClips and Events we will use. Then we created an instance of MenuSlidesMC, and added it to the stage.

    Now create a new ActionScript 3.0 file for the menuSlidesMC instance. Save it as MenuSlidesMC.as and copy the following code into it:

    
    
    package{
    	import flash.display.MovieClip;
    	import flash.events.Event;
    	import flash.events.MouseEvent;
    
    	public class MenuSlidesMC extends MovieClip{
    		public var speed:Number = new Number();
    		public var activeSlide:Number = new Number();
    		public function MenuSlidesMC(){
    			speed = 10;
    			activeSlide = 1;
    			addEventListener(MouseEvent.CLICK, slidesClick);
    			addEventListener(Event.ENTER_FRAME, slidesMove);
    		}
    	}
    }
    

    Just like last time, we imported what we are going to need, but we created two number variables. The first variable, speed, is actually how many pixels the slides are moved by each frame. (Note: this number has to evenly divide into your stage’s width to give a smooth transition). The second variable, activeSlide, tells us which slide is currently set to be on screen.

    We also added two event listeners for functions we are going to create; one of them is called on a mouse click, and the other is called at the beginning of every frame.


    Step 5: Creating the Event Handler Functions

    To begin we will get the mouse click function out of the way. Start by creating a public function named slidesClick():

    
    
    public function slidesClick(event:MouseEvent):void {
    
    }
    

    Next we will create some if-statements regarding the event.target.name. Basically, this property stores the name of the object that was targeted by the mouse click. We can use this to check which button is pressed:

    
    
    if(event.target.name == "left"){
    	if(activeSlide>1){
    		activeSlide-=1;
    	}
    }else if(event.target.name == "right"){
    	if(activeSlide<4){
    		activeSlide+=1;
    	}
    }
    
    if(event.target.name == "one"){
    	activeSlide=1;
    }else if(event.target.name == "two"){
    	activeSlide=2;
    }if(event.target.name == "three"){
    	activeSlide=3;
    }else if(event.target.name == "four"){
    	activeSlide=4;
    }
    

    The code above goes in the slidesClick() function. The first set of if-statements are for the left and right side buttons; they increase or decrease the value of activeSlide, but never allow the value to become less than 1 or greater than 4 (since we only have four slides). The second set of if-statements are for the circle buttons; instead of just incrementing or decrementing the value of activeSlide they set it to the selected value.

    Now let’s begin with the ENTER_FRAME handler function:

    
    
    public function slidesMove(event:Event):void {
    
    }
    

    Add the slidesMove() function below your slidesClick() function and we’ll start adding some code to it. First, we’ll use a switch to check which slide should be on the screen, based on the value of activeSlide:

    
    
    switch (activeSlide){
    case 1:
    
    break;
    case 2:
    
    break;
    case 3:
    
    break;
    case 4:
    
    break;
    }
    

    Now in each case we will create an if/else block that will check that slide’s current x-position, and move all of the slides either left, right, or not at all, depending on where the desired slide currently sits.

    The first case looks like this:

    
    
    if(slide1.x<0){
    	slide1.x+=speed;
    	slide2.x+=speed;
    	slide3.x+=speed;
    	slide4.x+=speed;
    }else if(slide1.x>0){
    	slide1.x-=speed;
    	slide2.x-=speed;
    	slide3.x-=speed;
    	slide4.x-=speed;
    }
    

    Now all we have to do is repeat the same process for the other cases! After you are done your swtich should look like this:

    
    
    switch (activeSlide){
    	case 1:
    		if(slide1.x<0){
    			slide1.x+=speed;
    			slide2.x+=speed;
    			slide3.x+=speed;
    			slide4.x+=speed;
    		}else if(slide1.x>0){
    			slide1.x-=speed;
    			slide2.x-=speed;
    			slide3.x-=speed;
    			slide4.x-=speed;
    		}
    	break;
    	case 2:
    		if(slide2.x<0){
    			slide1.x+=speed;
    			slide2.x+=speed;
    			slide3.x+=speed;
    			slide4.x+=speed;
    		}else if(slide2.x>0){
    			slide1.x-=speed;
    			slide2.x-=speed;
    			slide3.x-=speed;
    			slide4.x-=speed;
    		}
    	break;
    	case 3:
    		if(slide3.x<0){
    			slide1.x+=speed;
    			slide2.x+=speed;
    			slide3.x+=speed;
    			slide4.x+=speed;
    		}else if(slide3.x>0){
    			slide1.x-=speed;
    			slide2.x-=speed;
    			slide3.x-=speed;
    			slide4.x-=speed;
    		}
    	break;
    	case 4:
    		if(slide4.x<0){
    			slide1.x+=speed;
    			slide2.x+=speed;
    			slide3.x+=speed;
    			slide4.x+=speed;
    		}else if(slide4.x>0){
    			slide1.x-=speed;
    			slide2.x-=speed;
    			slide3.x-=speed;
    			slide4.x-=speed;
    		}
    	break;
    }
    

    And that’s it! We are all finished with the code and the menu should be working great right now.


    Conclusion

    Thank you for taking the time to read through the tutorial, I hope it was helpful and that you learned a little something about dynamic menus.


  2. Philip Thonbo says:
    December 9, 2011 at 10:27 pm

    Twice a month, we revisit some of our readers’ favorite posts from throughout the history of Activetuts+. This tutorial was first published in April, 2009.

    In this tutorial we’ll create a magnifying glass effect, demonstrating use of the displacementMapFilter. The effect can be achieved in a relatively short space of time and with very little code.


    Final Result Preview

    Let’s take a look at what we’re aiming for:


    Step 1: Brief Overview

    We’re going to work with two layers, plus an additional optional layer. The first will hold an image which will contain the visual graphics, this can be anything. The second layer will be the color map which will control the pixel pushing. The third layer will hold the ActionScript.

    An optional fourth layer will be an overlaying graphic acting as the frame or lens surround.

    Lets look into it!


    Step 2: Document Setup

    First thing we need to do is make a new ActionScript 3.0 Flash file – make the document size 530px X 400px with a framerate of 30fps.

    ””

    Step 3: Import Resources

    Next we need to import an image that we can use for this effect – I found a cool, freely available desktop image at 1024px X 768px.

    Import this to stage and name the layer "Image".

    ””

    Now let’s scale the image down to 50% and center it.

    ””

    Step 4: Scripting the Filter

    Create a new layer on top and call it "Actions". Then let’s bring the actions panel out and start coding the effect. First we need the filter for the image so let’s create a new filter object and call it "dFilter". We’ll leave the filter free of parameters as there are quite a few to set.

    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    

    Next we need to set these filter parameters in listed view.


    Step 5: Effect Scale

    Let’s start with the easiest ones and set the scales to around 50. This is the amount to which the magnifier will zoom in. It can also be set to a negative value, but in this case we need it to zoom in, not out.

    Additional lines: 3,4

    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    

    Note: this is not the actual order in which the filter normally accepts the parameters. However, in this case we can add them as we wish because we’re using the listed view for a better overview.


    Step 6: Color Channel Components

    Next we’ll set the component color channels for X and Y – this dictates which colorchannels in the control map (which we’ll create in a second) the filter will listen to.

    If you’re familiar with the RGB hex code #RRGGBB, we can choose from BitmapDataChannel.RED, BitmapDataChannel.GREEN and BitmapDataChannel.BLUE. To make it easier we can also just write 1 (red), 2 (green) or 4 (blue) – (and no I didn’t make a spelling mistake, the blue is 4; this is set from the actual channel position in the hex code). In this example we’ll just stick to red (1) and green (2)- but we’ll come back to more about this when we design the actual displacement map.

    Additional lines: 5,6

    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    

    Step 7: Displacement Mode

    Next we need to set the mode to determine how the pixels will react if they are pushed further than the image boundaries. Here we can choose from:

    DisplacementMapFilterMode.COLOR / DisplacementMapFilterMode.WRAP / DisplacementMapFilterMode.CLAMP / DisplacementMapFilterMode.IGNORE

    Again we can simplify this by writing "color", "clamp", "wrap", "ignore". I won’t get any further into these in this tutorial, so lets just use “color” which works best in most cases.

    Additional lines: 7

    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    

    This mode allows pixels to continue beyond the image boundary (in case the filter pushes the pixels further than the edge of the image).


    Step 8: Surrounding Color and Alpha

    Now let’s set the surrounding color to 0×000000 and alpha to 0. This is 100% transparent, so nothing is displayed outside the image except the source pixels.

    Additional lines: 8,9

    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha		= 0
    

    Step 9: Filter Effect Position

    Now we need to set the position where the filter will affect the image; our lens position. This has to be set as a Point object containing the x and y value. We’ll begin by creating the point object so it’s ready for use when we assign it to the displacementMapFilter. Let’s call it "dPoint" and set it to 0, 0 as initial values. We’ll come back to this in a moment when we need to instruct this point to follow the mouse.

    Next we assign "dPoint" to the "dFilter’s" point position.

    Additional lines: 1,11

    var dPoint:Point = new Point(0, 0);
    
    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha		= 0
    dFilter.mapPoint	= dPoint;
    

    Step 10: BitmapData

    Last but not least we need to assign the control map to the filter. This is the map which contains the colored pixels that the componentX and Y listen to.

    Additional lines: 13

    var dPoint:Point = new Point(0, 0);
    
    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha		= 0
    dFilter.mapPoint	= dPoint;
    dFilter.mapBitmap	=
    

    Here we also need a BitmapData object to act as a data container for our color-map.


    Step 11: Designing the Color Map

    First we create a 100px X 100px, red to black, linear gradient square. This will take the current pixels and push them left and right as we set the componentX to red. Let’s make this a movieclip called "redMap"

    Then we do the same again – but this time with a green to black linear gradient square, again 100px X 100px. This time we’ll also rotate it 90°. You might remember we set the component for the Y axis displacement as green (componentY = 2) so the gradient goes along the y axis. Once again we’ll convert it to a movieclip, this time calling it "greenMap"

    ””

    Step 12: Preparing the Map for Capture Phase

    We now have two separate color images; we need just one, so set the blendmode of the greenMap to "screen". Every color from the greenMap will then shine through on the redMap. Place the greenMap on top of the redMap and make sure they align correctly.

    Select both movieclips by clicking on the layer "Map" and convert the two into one movieclip called "colorMap". Then set the instance name to "colorMap_mc".

    ””

    Step 13: Map Container

    Now let’s return to the code and continue by capturing the colorMap movieclip in a bitmapData.

    Go to the top of the code and create a new BitmapData object. Let’s call it "dMap" and set the size of it to match the size of our colorMap (in this case 100px X 100px, but this can be almost anything). We’ll set transparent to "true" and color to 0×808080. This ensures that any remaining pixels in the bitmapData are neutral.

    Additional lines: 3

    var dPoint:Point = new Point(0, 0);
    
    var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
    
    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha		= 0
    dFilter.mapPoint	= dPoint;
    dFilter.mapBitmap	=
    

    Step 14: Capture Phase

    We need to draw the colorMap’s content into the bitmapData. Once that’s done, we’ll be able to use script to delete the colorMap from the stage. This is possible as the colorMap image will be contained within the bitmapData code.

    Additional lines: 5, 7

    var dPoint:Point = new Point(0, 0);
    
    var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
    
    dMap.draw(colorMap_mc)
    
    removeChild(colorMap_mc)
    
    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha		= 0
    dFilter.mapPoint	= dPoint;
    dFilter.mapBitmap	=
    

    Step 15: Assigning the Map to the Filter

    Add the bitmapData dMap to the displacementMapFilter by setting the last parameter in the list (mapBitmap) to "dMap".

    Modified lines: 19

    var dPoint:Point = new Point(0, 0);
    
    var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
    
    dMap.draw(colorMap_mc)
    
    removeChild(colorMap_mc)
    
    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha		= 0
    dFilter.mapPoint	= dPoint
    dFilter.mapBitmap	= dMap
    

    Step 16: Add Filter to Image

    The filter is complete! We now need to add it to the image, so select the image and make sure it has an instance name – lets call it "Image_mc". That done, we’re able to set the filter on the image. We do this at the end of the code by setting the Image filters parameter as an array like this:

    Image_mc.filters = [dFilter]

    Additional lines: 21

    var dPoint:Point = new Point(0, 0);
    
    var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
    
    dMap.draw(colorMap_mc)
    
    removeChild(colorMap_mc)
    
    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha		= 0
    dFilter.mapPoint	= dPoint
    dFilter.mapBitmap	= dMap
    
    Image_mc.filters = [dFilter]
    

    OK, let’s export the movie and see how the filter is affecting the image. It should look something like this:


    Step 17: Interactivity

    What we have so far isn’t very exciting, so let’s try to make the lens follow the mouse.

    First we add the "enterFrame" loop code like this:

    Additional lines: 23,25,27

    var dPoint:Point = new Point(0, 0);
    
    var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
    
    dMap.draw(colorMap_mc)
    
    removeChild(colorMap_mc)
    
    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha		= 0
    dFilter.mapPoint	= dPoint
    dFilter.mapBitmap	= dMap
    
    Image_mc.filters = [dFilter]
    
    Image_mc.addEventListener(Event.ENTER_FRAME, onFrame)
    
    function onFrame(e:Event){
    
    }
    

    Step 18: Follow the Mouse

    Next we set the values of our dPoint’s X and Y to follow the mouse. Additionally, we’ll reassign the newly changed dPoint to the dFilter again and reassign the filter to the image.

    Additional lines: 26,27,28,29

    var dPoint:Point = new Point(0, 0);
    
    var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
    
    dMap.draw(colorMap_mc)
    
    removeChild(colorMap_mc)
    
    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX		= 50
    dFilter.scaleY		= 50
    dFilter.componentX	= 1
    dFilter.componentY	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha		= 0
    dFilter.mapPoint	= dPoint
    dFilter.mapBitmap	= dMap
    
    Image_mc.filters = [dFilter]
    
    Image_mc.addEventListener(Event.ENTER_FRAME, onFrame)
    
    function onFrame(e:Event){
    	dPoint.x = mouseX
    	dPoint.y = mouseY
    	dFilter.mapPoint = dPoint
    	Image_mc.filters = [dFilter]
    }
    

    Lets test it again. It should look like this:


    Step 19: Finalizing

    It’s still not exactly how we want it, so lets make the center of the displacement follow the mouse and also add a small easing to the movement. To do that we change the following code:

    dPoint.x = mouseXdPoint.y = mouseY

    Modified lines: 26,27

    var dPoint:Point = new Point(0, 0);
    
    var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
    
    dMap.draw(colorMap_mc)
    
    removeChild(colorMap_mc)
    
    var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
    
    dFilter.scaleX 		= 50
    dFilter.scaleY 		= 50
    dFilter.componentX 	= 1
    dFilter.componentY 	= 2
    dFilter.mode		= "color"
    dFilter.color		= 0x000000
    dFilter.alpha 		= 0
    dFilter.mapPoint	= dPoint
    dFilter.mapBitmap	= dMap
    
    Image_mc.filters = [dFilter]
    
    Image_mc.addEventListener(Event.ENTER_FRAME, onFrame)
    
    function onFrame(e:Event){
    	dPoint.x += ((mouseX-colorMap_mc.width/2)-dPoint.x)*0.3
    	dPoint.y += ((mouseY-colorMap_mc.height/2)-dPoint.y)*0.3
    	dFilter.mapPoint = dPoint
    	Image_mc.filters = [dFilter]
    }
    

    To sum up: we subtract half the size of the map from the map position, so it centers. Then we add a basic tweening function, which can be written like this:

    this += (that-this)*speed


    Step 20: Adding Custom Graphics

    To top it off, I added a magnifying glass graphic that I prepared in photoshop. I converted it into a movieclip, gave it an instance name and made it follow the point that we use for the displacemenMapFilter.

    ””

    This is achieved by setting the new lens_frame_image X and Y position equal to the dPoint position. Then subtract the offset for the graphics edge, so that it aligns perfectly with the filter effect.

    Additional lines: 4,5

    function onFrame(e:Event){
    	dPoint.x += ((mouseX-colorMap_mc.width/2)-dPoint.x)*0.3
    	dPoint.y += ((mouseY-colorMap_mc.height/2)-dPoint.y)*0.3
    	lens_mc.x = dPoint.x-8
    	lens_mc.y = dPoint.y-8
    	dFilter.mapPoint = dPoint
    	Image_mc.filters = [dFilter]
    }
    

    Now our result should look like this:


    Conclusion

    When you have learned to create this effect yourself it shouldn’t take more than 15 minutes to set up. Remember; if you forget what the parameters for the displacementMapFilter are you can always look them up on "help". There you will get the listed order and what each parameter does.

    For quick experimentation you can go to my website and look in the "flash" section under "test / labs" – I have a bunch of displacementMapFilter test environments you can try out.

    I hope you can find use for this filter in your creative work!


  3. Carl Schooff says:
    December 9, 2011 at 10:50 pm
    This entry is part 5 of 5 in the series TimelineLite Ultimate Starter Guide

    I’m excited to reveal to you the most powerful tools in the entire GreenSock Tweening Platform. Everything I have discussed in the last four videos has been custom tailored to prepare you for the awesome power you are about to behold. I’m going to show you two methods that will change the way you approach any script-based animation from this point forward.

    With appendMultiple() and insertMultiple() you will have precise control over the sequencing and timing of hundreds of tweens and timelines with very little code.


    TimelineLite in Action

    In the SWF below, the parent timeline that is being controlled by the scrubber only has two lines of code, yet there are literally over a hundred tweens taking place.

    You can find all the files used to create the SWF above in the source files for this tutorial.


    Watch the Screencast

    Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


    Meet appendMultiple()

    TimelineLite’s appendMultiple() method allows you to add many tweens and/or timelines to a timeline and have precise control over the relative timing of all the tweens/timelines. What makes this method so powerful is that it accepts an array of tweens/timelines and treats them all as single group that can be offset and staggered however you like.

    In order to get most out of appendMultiple() you must understand all four parameters.

    appendMultiple(tweens:Array, offset:Number = 0, align:String = "normal", stagger:Number = 0):Array

    tweens:Array — an Array containing any or all of the following: TweenLite, TweenMax, TimelineLite, and/or TimelineMax instances

    offset:Number (default = 0) — Amount of seconds (or frames for frames-based timelines) to offset the insertion point of the tweens from the end of the timeline. For example, to start appending the tweens 3 seconds after the end of the timeline (leaving a 3-second gap), set the offset to 3. Or to have the tweens appended so that the insertion point overlaps with the last 2 seconds of the timeline, set the offset to -2. The default is 0 so that the insertion point is exactly at the end of the timeline.

    align:String (default = “normal”) — determines how the tweens will be aligned in relation to each other before getting appended. Options are: TweenAlign.SEQUENCE (aligns the tweens one-after-the-other in a sequence), TweenAlign.START (aligns the start times of all of the tweens, ignoring delays), and TweenAlign.NORMAL (aligns the start times of all the tweens, honoring delays). The default is NORMAL.

    stagger:Number (default = 0) — staggers the tweens by a set amount of time (in seconds) (or in frames for frames-based timelines). For example, if the stagger value is 0.5 and the “align” property is set to TweenAlign.START, the second tween will start 0.5 seconds after the first one starts, then 0.5 seconds later the third one will start, etc. If the align property is TweenAlign.SEQUENCE, there would be 0.5 seconds added between each tween. Default is 0.

    The above descriptions were taken directly from the GreenSock Documentation.

    In the video I go over a number of ways to create the array of tweens that appendMultiple() will accept. Below are the two most popular approaches.

    Create an Array of Unique Tweens

    
    
    tl = new TimelineLite();
    
    //bg tween
    tl.insert( TweenMax.to( bg, .5, {alpha:1});
    
    tl.appendMultiple( [TweenLite.from( meet_mc, .5, {x:-100, rotation:-90, scaleX:0, scaleY:0, ease:Back.easeOut} ),
    					TweenLite.from( the_mc, .5, {y:-100, rotation:-90, scaleX:0, scaleY:0, ease:Back.easeOut} ),
    					TweenLite.from( blobs_mc, .5, {x:700, rotation:90, scaleX:0, scaleY:0, ease:Back.easeOut} ) ],
                        0, "sequence", .5);
    

    In the code above three tweens added via appendMultiple() will be added immediately after the bg tween ends because the offset value is 0. Each tween will start .5 seconds after the previous tween ends because the align parameter is set to “sequence” and the stagger is set to .5.

    Create an Array of Similar Tweens Using allFrom()

    TweenMax.allFrom() creates an array of tweens based on an array of objects. It applies the same values to tweens of all the objects in the array. You can also use TweenMax.allTo() if you want to specify where objects should tween to as opposed to where they should tween from.

    
    
    
    //create an array of objects to be tweened
    allBlobs = [blob1_mc, blob2_mc,  blob3_mc, blob4_mc,  blob5_mc, blob6_mc,  blob7_mc]
    
    tl = new TimelineLite();
    
    //use allFrom() to tween every blob FROM the same set of properties with the same duration.
    tl.appendMultiple( TweenMax.allFrom( allBlobs, .3, {scaleX:0, scaleY:0, x:"100"} ), 0, "normal", .1 )
    

    The code above will tween each blob for .3 seconds from the values supplied in the vars object ({scaleX:0, scaleY:0, x:"100"}). Each tween will start .1 second after the previous tween has started because the align mode is set to “normal” and the stagger is .1.

    It’s important to note that allFrom() returns an array of tweens and that is why we can use it as the value for the tweens parameter in the appendMultiple(). If you were to use allFrom() in an append() you would get an error as it requires a single tween rather than an array of tweens.


    TweenAlign Visualizer

    Align modes are a bit difficult to understand without seeing them in action. I built the TweenAlign visualizer to give you an easy way to test how they work with a combination of various tween delays, staggers and offsets.

    Use the swf above to perform the following tests:

    Test 1: Understand the difference between TweenAlign.NORMAL and TweenAlign.START

    • Set bar 1 delay to 2
    • Toggle between TweenAlign.NORMAL and TweenAlign.START

    Notice how the delay is ignored with TweenAlign.START

    Test 2: See how the stagger works differently depending on align mode

    • Set all tween durations to 1
    • Set all tween delays to 0
    • Set stagger to 1
    • Toggle between TweenAlign.NORMAL and TweenAlign.SEQUENCE

    Notice how stagger works differently with TweenAlign.NORMAL and TweenAlign.START:

    • Using TweenAlign.NORMAL, stagger is the amount of time between the start of each tween.
    • With TweenAlign.SEQUENCE, stagger is the amount of time between the end of a tween and the next tween.

    Go crazy combining different settings and keep an eye on how they effect the start time of each tween and the overall duration of the timeline. The TweenAlign Visualizer is also available in the source files for this tutorial.

    Additional Notes

    Although I reference appendMultiple() quite a bit in this text, insertMultiple() works virtually the same way. The only difference with insertMultiple() is that the offset parameter refers to an exact time or label at which the tweens/timelines should be added. Read more in the TimelineLite Documentation.

    When specifying the align mode you can reference the static contsant value in the TweenAlign class or the string value.

    TweenAlign.NORMAL is the same as using “normal”.


    Conclusion

    Once you get a handle on how appendMultiple() and insertMultiple() work you basically have limitless potential for creating elaborate and flexible animations with very little code. I truly hope the demonstration of nesting multiple TimelineLites inspires you to create some truly wonderful effects. By adding just a touch of randomness to each timeline you can really start to take your animations to the next level and maintain an insane amount of control.

    Perhaps now you have the knowledge and fortitude to attempt the “starburst” effect that was featured in the Introduction to TimelineLite video? Come to think of it, I’m assigning that challenge to you as homework.

    In the next tutorial I am going to be showing some features exclusive to TimelineMax and some other tricks you can do with all your timelines.

    If you have any questions or comments on this tutorial simply post a comment below.

    Thanks for watching!


  4. Activetuts+ Editor says:
    December 9, 2011 at 11:08 pm

    Are you an RIA developer? Do you make Flash games or Unity games? Are you always on top of the latest industry news? You sound like the perfect person to contribute to Activetuts+!

    We’re on the lookout for new authors, so read on to find out more…


    What We’re Looking For

    Right now, we’re putting out a general call for bloggers.

    Okay, technically everything on Activetuts+ could be considered a blog post. What we mean, specifically, is the more chatty, conversational posts; articles that aren’t focused on building a specific type of app, or implementing a certain effect.

    The best way to illustrate this is through a few examples from other Tuts+ sites. Some articles clear up misconceptions, offer advice, or discuss a pertinent issue:

    • Why Many Developers Hate ASP.NET… and Why They’re Wrong
    • Should You Watermark Your Art?
    • Elements of a Great Web Design Portfolio
    • 5 Cardinal Sins of WordPress Theme Development

    Other posts help readers discover useful and inspirational content that’s relevant to their niche:

    • A Look into Shashthree’s Latest Experiment “Quote Unquote”
    • 50 Fabulous Photos of Joyous Celebrations
    • 50 Practical, Problem Solving Items From ThemeForest
    • Massive Collection of Vintage Vector Graphics

    Payment will depend on the length, depth, and subject of the article, but you can expect to earn from $50 to $150 per post.


    Pitch a Blog Post

    Got an idea? Great! Pitch it to us (in about a paragraph or so) using the following form:

    Pitch your Quick Tip idea

    As long as you’ve got an original, useful idea and can string a decent English sentence together, there’s a high chance your pitch will be accepted, so don’t be shy.

    No specific ideas? That’s okay, we’re still interested – just submit some relevant examples of previous writing you’ve done, whether it’s on your own blog, on forums, or even on Google+.

    Of course, this is also open to existing Activetuts+ writers, past and present – you know how to get in touch.

    We’re looking forward to reading your pitches!


  5. Rahul R Gaikwad says:
    December 9, 2011 at 11:44 pm

    In AS3 projects, you often need to load external assets like images and other SWFs. While loading these assets you have to keep track of several events for successful execution of your application. You might have been using some of these events like ProgressEvent, COMPLETE event. This tutorial shows you how to get info about the assets you’re loading with Loader.load(), using its associated events, all in one place. So if you’re having difficulty loading such assets, or you have less time in hand to debug, take a look at this.

    (Preview image courtesy of VisualPharm.)


    Final Result Preview

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

    This SWF loads an image, showing details about the loading process (progress, whether it’s complete, and more).

    It won’t work embedded in this page (which shows you the responses in case of error) but it will work if you load the SWF directly.


    Step 1:The need to load assets

    Hey, if you are in a hurry, you can skip this step. But, if you are relaxed, with a cup of coffee in hand, have a read.

    In the early days when I started learning Flash 5 and AS1, I used to have all objects on the stage at once, and made them visible/invisible as required. Eventually as I started developing apps, I became more familiar with Flash’s system. Wow, now I was able to use “linkage identifier” to load objects from library. Getting more advanced, I soon realised the need for external assets. But unfortunately, there was no such powerful architecture. Meanwhile, Flash was going through drastic changes. Now “AS2″ was capable of loading external assets. Finally, when it lined up in Adobe’s family, the new event-based architecture “Action Script 3.0″ was introduced. In AS3, the need for loading external assets is much better addressed than in AS2.

    So, when working with Flash we have three ways to manage our assets:

    1. Put all required assets (MovieClips with instance names) on the stage and manipulate them as required.
    2. Put all required assets in the Library and access them using “Identifier” in library panel.
    3. Put all or some required assets outside Flash and load them dynamically.

    The first method is not versatile. As the number of objects increases, the size of the SWF also increases (especially when there are lots of images). Imagine how much time it can take to load on user’s machine? Also, the performance of your application might degrade. But, still it can be handy enough for creating lightweight apps. (E.g. developing a simple game, in which player needs to find out key objects from the given image).

    The second method is very much similar to the first one. Instead of having objects on the stage, now they are residing only in the library. Again, if there are lots of objects, then the issues with the SWF’s size and performance remain. But with this approach, you can easily create multiple instances of objects. Plus, the objects are much easier to handle than the first method. (E.g. games like “Tic Tac Toe”, “Tetris”, and “Snake” can be developed as they require fewer objects).

    The third method (loading assets externally) is much more flexible than the first two. The power of this method is, without having a single object in the library you can still develop big games (e.g. “RPG” style games). As objects are loaded externally, they are loosely tied to your main SWF, so you do not have to go back to Flash every time you want to replace or edit your assets. One more advantage of this method is, it allows you to load and display objects on an “On Demand” basis. Meaning, you can load your objects only when they are required and unload them when you are completely done. (E.g. if your game has 10 levels, then you do not need to load all assets needed for all 10 levels. Instead, load and unload them level by level.) Thus, the overall performance of the application is improved.

    Note: The above “On Demand” method may not be suitable in case where assets are loaded and unloaded frequently (e.g. in an image viewer app).

    Okay, so now we can conclude that, of the three methods, the third one is more flexible. But, as the system gets more advanced, it becomes more complicated to manage. Similarly, if you decide to go with third method, you will need to handle assets as one separate operation. You may call it “Asset Management” which can be divided into two parts:

    • Handling assets manually (involves folder structures and operations like cut-copy-paste)
    • Handling assets programmatically (involves loading, displaying, and unloading in a program)

    This tutorial covers the second part, so let’s look at that now.

    As our program loads assets externally, it is now dependent on those assets. If any of our assets fail to load for some reason, then our entire application will be hampered. To avoid such failures, we really have to provide “Decision Making” power to our program.

    Here’s one example. You have a coin-flipping game, where the coin is an externally loaded image. Now, if this image fails to load, then what next? This is the perfect point where your program will take some decision(s). It might load another image for the coin, stored as a proxy. It might load the stand-by coin if you have placed it in the Flash library. This can be a lightweight coin made up of vector graphics and strokes converted to fill to keep the size of the main SWF as small as possible. If you do not plan to have stand-by coin, then your program could warn the user about failure.

    Of course, this was just one case. For a complete game, you will need to use a mature “Asset Management” system.


    Step 2: Which Type of Loader?

    In an AS3 project, assets can be any of the following,

    1. Images.
    2. SWFs.
    3. Sounds.
    4. Videos.
    5. Text files (including Text, XML, JSON, and sometimes Binary Data).

    These assets have their own methods of loading as they are different in nature. You cannot see the sound, and you cannot hear images, so it is quite acceptable to have different techniques for these different types.

    Hence, you cannot load sounds the way you load images and vice versa. You have to pick the right method for the selected assets.

    The following are the appropriate ways of loading these assets :

    1. Images and SWFs: “load()” method of “Loader” class is used to load images and SWFs. Our tutorial is dedicated to this section.
    2. Sounds: “load()” method of “Sound” class is used to load external MP3 sound files.
    3. Videos:

      FLV video format or a video format that uses standard H.264 encoding is supported by AS3.

      Video without FLV component can be loaded and streamed using classes like “NetConnection” and “NetStream“.

      Video with FLV component can be loaded and streamed using “source” method as myFLVComponent.source("MyVideo.flv").

    4. Text files (including Text, XML and sometimes Raw Binary Data):
    5. To load such type of data, you have to use the URLLoader class, which loads data from the specified URL. Any type of data can be loaded but in the form of text or raw binary data or encoded variables.

      e.g. You can also load an image in the form of raw binary data and further use it for processing with “ByteArray” class.

    So, let us end the theoretical part here and move towards the practical stuff. Now we have enough knowledge about assets. In the rest of the tutorial, we will be dealing with the load() method (of “Loader” class) and its associated events, to monitor the loading process of an image and a SWF.


    Step 3: Events for Monitoring the Loading Process

    Before moving towards Loader class, first let us look at several events that are needed to monitor the loading operation:

    • IOErrorEvent.IO_ERROR
    • Our first task will be to check the availability of the specified target (i.e the “loadee”).

      Sometimes, the target is not found due to incorrect file names or perhaps because the file itself no longer exists at the location. Even, in some cases, assets may not be readable. If everything is okay at this level, then we can jump to monitoring the loading process.

    • Event.OPEN
    • As soon as the loading is triggered, this event is dispatched. Here, we can initialize a preloader (e.g. set up the Progress indicator), before the PROGRESS event is dispatched. This OPEN event is the first thing to be dispatched in a (successful) loading operation.

      This event depends on the loading environment. Meaning, if you are loading images remotely (say, over the Internet, rather than from the user’s hard drive) and if the connection is okay but the file is not found, even now this event will be dispatched. So, be careful if you are initializing a preloader here – or try to make your program very strict in handling an IO_Error event.

    • ProgressEvent.PROGRESS
    • We have got the target and now the loading is in progress. But we can’t just stay quiet and wait for the progress event to finish, because it takes some time to load the image (or SWF), especially when the image is heavy or being transferred online. So, to keep the user engaged, we must keep informing him about the state of the load. Now, what to inform?

      While is in progress, we can display the message saying “Please wait. File is loading”. We can also display the “current bytes loaded” on the screen using information from the PROGRESS event.

      We can do such tasks while this event is processing. Hence, it is at second position.

    • Event.INIT
    • This event is best suited for downloading SWF files from the Internet.

      If you are loading SWF from local machine itself and the SWF is lightweight, then it is almost identically timed to the COMPLETE event. Many a time you will find no difference between INIT and COMPLETE events, because within no time, you are in a state of COMPLETE, immediately leaving INIT state.

      But the situation changes when you are loading the SWF(s) from internet. In addition, if the SWF (having animations or lots of objects) is the target, then it will take more time to download. In this case the INIT becomes handy.

      As soon as the SWF header is readable, this event is dispatched and the document class for the main SWF is instantiated. The first frame is available and you can do some preloading actions or you can define some properties while the rest of the part is still downloading.

      This event is the third to fire in a successful load.

    • HTTPStatusEvent.HTTP_STATUS
    • When loading assets over the Internet (using an HTTP request), the HTTP status code (e.g. 200) is returned if the connection is OK. Otherwise, 0 is returned.

      If the connection is okay, but the file is not found, then 404 is returned.

      For more information on HTTP Status Messages, follow the link below:

      HTTP Status Messages

      Although this event checks the status of the connection to the remote server, it is trigerred even in case of loading assets locally – but in this case it always returns 0. This event fires fourth.

    • Event.COMPLETE
    • As the name suggest, this event will be dispatched when an image (or SWF) is completely loaded on the user’s machine. At this point, the image or SWF is completely available for further process. Hence, this event is at last place in the loading operation.

    There are also some other events like so:

    • AsyncErrorEvent.ASYNC_ERROR:
    • This error occurs when a SWF, running asynchronous code (like AS2), is loaded.

    • SecurityErrorEvent.SECURITY_ERROR:
    • This error occurs when Flash Player’s security model is violated during a loading process.

      For the latest info on the security model of Flash Player, take a look at Flash Player Security.

    For more info on SecurityErrorEvent.SECURITY_ERROR specifically, here are some links to follow:

    • SecurityErrorEvent
    • Security Class

    Although we can skip some of these events – like “OPEN”, “HTTPStatus”, “INIT” – when loading assets locally, tracking all of them ensures a high level of monitoring a loading operation.


    Step 4: Preparing the Document Class

    After knowing all necessary event types, now its time for loading assets.

    First, we shall create a basic structure of our document class.

    For detailed explanation about the document class check out this Quick Tip.

    Download all source files required for this assignment by clicking the “Download Source Files” button available at the top of the page.

    The folder contains “LoaderClassExample.fla”, “MyImage.png”.

    Also, there is “MyLoader_Complete.as” file, from the end of the tutorial. We are going to build this class, step by step, for better understanding. At the end of this tutorial, we will have our own version of this class.

    Open Flash and create new “ActionScript 3.0 Class” file and name it “MyLoader”.

    You will have the basic structure of the class like so:

    
    
    package  {
    
    	public class MyLoader {
    
    		public function MyLoader() {
    			// constructor code
    		}
    	}
    }
    

    Save this class file as “MyLoader.as” in the same downloaded folder.

    Then open the downloaded “LoaderClassExample.fla” file. Don’t worry about the objects on the stage. We shall see their roles in coming steps.

    So, first we must change the document class from “MyLoader_Complete” to “MyLoader”, in the Property Inspector of the FLA.

    Now, the Class name must read like so:

    Change the document class name

    Step 5: Loading an Image

    To start with, we will load the image “MyImage.png” placed in the downloaded folder.

    The basic requirements can be listed down, like so:

    • Loader Class to create Loader Object.
    • URLRequest Object to specify the path of an image.
    • load() method of Loader Class.
    • Display the image on the screen.

    So, to fulfill above requirements, modify the “MyLoader.as” like so:

    
    
    package  {
    
    	import flash.display.Sprite;
    	import flash.display.Loader;
    	import flash.events.MouseEvent;
    
    	import flash.net.URLRequest;
    
    	public class MyLoader extends Sprite {
    
    		private var myURL:String;
    		private var loader:Loader;
    
    		public function MyLoader() {
    
    			myURL = "MyImage.png";
    
    			loader = new Loader();
    			addChildAt(loader,0);
    
    			loadButton.addEventListener(MouseEvent.CLICK, loadAsset, false, 0, true);
    		}
    
    		private function loadAsset(evt:MouseEvent):void {
    
    			loader.load(new URLRequest(myURL));
    
    			removeChild(loadButton);
    
    			loadButton.removeEventListener(MouseEvent.CLICK, loadAsset);
    		}
    	}
    }
    

    Test the movie and click the “Start Loading” button. The image is loaded and displayed.

    Since, the target was an image, we needed Loader Class to create Loader Object.

    Hence, in our code we put the lines like so:

    
    
    import flash.display.Loader;
    

    Above line made the Loader class available to our program.

    
    
    private var loader:Loader;
    

    Above line declared the loader var to store Loader object.

    
    
    loader = new Loader();
    

    Above line created the Loader object and assigned it to a loader var.

    Now, we can access load() method of Loader class.

    In our code, we accessed load() method like so:

    
    
    loader.load(new URLRequest(myURL));
    

    The load() method is most crucial part of our code.

    We passed only one parameter as URLRequest to this method. Actually it can take two parameters. The second parameter is LoaderContext object. The URLRequest is required while LoaderContext is optional parameter.

    For example, loader.load( URLRequest, LoaderContext);

    Let’s look at brief info about URLRequest and LoaderContext in next couple of steps.


    Step 6: URLRequest and Paths

    In our code, we created the instance of URLRequest object like so:

    
    
    loader.load(new URLRequest(myURL));  //myURL is a String
    

    We used a shorthand method for creating an instance of URLRequest, which is okay for our example but not a good practice in general. It should not be used for big projects (e.g. a framework). The problem is that it leaves no reference to the URLRequest that we can use again later.

    Instead, use this approach:

    var urlRequest:URLRequest = new URLRequest();

    urlRequest.url = myURL;

    loader.load(urlRequest);

    Now you can refer to urlRequest any time you want.

    Now, let us learn about URLRequest, absolute paths, and relative paths.

    URLRequest: This object gives us the ability to address the target by specifying a path.

    This path can be one of two types:

    1. Absolute Path – gives the full path to an asset.
    2. Here are some examples of Absolute Path:

      • http://SomeDomain/assets/MyImage.png
      • D://MyProject/Assets/MyImage.png

      Absolute Path is used mostly to download assets from other domains over the Internet. Being hard-coded, these paths do not give a flexible approach. Hence, for portable projects (especially for desktop apps) do not plan to use such paths.

      It uses standard URI schemes like so:

      • http
      • https (Secure http)
      • file

      Check this link for more info on Http and Https.

    3. Relative Path – gives part of the path to the asset.
    4. Relative Path can be divided into two parts like so:

      • Document Relative
      • MyImage.png (we used this path in the above code as myURL.)
      • Assets/MyImage.png
    5. Root Relative
      • ../Assets/MyImage.png
      • ../../Assets/MyImage.png

      Use case of above two paths depends on your project. But, in most cases you will end up using “Document Relative” path instead of “Root Relative” path.

      Document Relative path is illustrated like so:

      Document Relative

      (The SWF is in a folder parallel to the Assets folder.)

      Root Relative path is illustrated like so:

      Root Relative one step back
      Root Relative two step back

    Step 7: Loader Context

    We did not used this parameter in our example, but having information about it will add the value.

    Loader Context: This optional parameter gives access to the properties like so:

    • Security Domain
    • Application Domain
    • Check Policy file

    Let us see some brief info about these properties.

    • Security Domain

      loaderContext.securityDomain = SecurityDomain.currentDomain;

      This forces the loadee SWF (from other domain) to be placed into the loader SWF’s domain. By default the loadee SWF is placed in its own security domain (due to Flash Player’s security model).

      Also, a policy file (e.g. crossdomain.xml) must be available on the loadee SWF’s server in order to established the trust between different servers. Thus, ensuring the interoperability between SWFs.

      When loading images, this property is not required.

    • Application Domain

      Once, everything is in your own security domain, then you can specify loaderContext.applicationDomain.

      e.g. loaderContext.applicationDomain = ApplicationDomain.currentDomain;

      It allows cross scripting between SWFs. e.g. The loadee SWF can access the class associated with parent SWF, when set as ApplicationDomain.currentDomain.

      This property is not needed while loading images.

      Check this example which allows the access to class definition of loadee SWF.

      ApplicationDomain.currentDomain.getDefinition("com.SomeFolder.SomeAS3Class");
      ApplicationDomain.currentDomain.getDefinition("SomeLibrarySymbol") as Class;

      (Note: Be updated with Adobe’s policy about accessing external scripts. It is related to security model. Adobe is constantly improving Security model. So keep track of Adobe’s documentation.)

      Read the following links for more info on Application Domain:

      Application Domain

      Loader Context Application Domain

    • Check Policy file

      This property can be used for both (SWF and an image).

      e.g. loaderContext.checkPolicyFile = true;

      When this property is set to true, then it always checks for policy file (crossdomain.xml) on server side. If it is not found, a security sandbox error is thrown.

      Set this property to true only when you want to do more actions than just displaying that content on the screen. Otherwise keep this property as a false.

      e.g. When you are loading an image from the secure server and if you want to use BitmapData.draw method on that loaded content, then set this property to true.

    Following are some more links related to Flash Player Security:

    Security sandboxes

    Permission controls

    In this step we completed a very simple task of loading an image. But while loading we did not track the information about loading. We just watched and waited to have the image on the screen. In the next step we will see what is needed to monitor the loading progress of an image.


    Step 8: loaderInfo and contentLoaderInfo

    Friends, in the above step we loaded an image without tracking the loading information. This time we will start monitoring the loading process of this image. For that we will make use of various events we discussed in Step 3.

    But we still don’t know how to associate these events with Loader class. So, let us explore it.

    The Loader class comes with a very important property: contentLoaderInfo.

    This property is needed to associate the loading events with the load() method of Loader class.

    The following is one example, which tracks the COMPLETE event of loading process.

    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);

    When the target image is completely loaded, the “loadComplete” method is called. This method can have your after-loading logic, e.g. adding that image to the stage.

    We are definitely going to use this property very soon. But, before that, let us see what exactly it does with Loader class.

    The Loader class does not have any information about loading progress. In fact, this information is retrieved from the contentLoaderInfo which further utilizes the LoaderInfo object.

    What is loaderInfo? What is contentLoaderInfo?

    To understand these terms, we shall experiment with our “MyLoader.as” Class.

    This time we shall actually use COMPLETE event. So, let us add our new function loadComplete and some more lines to the code like so:

    
    
    import flash.events.Event;
    

    The above line makes the Event class available to our program. Thus we can use COMPLETE event.

    
    
    private function loadComplete(evt:Event):void
    {
    	trace("Load Complete");
    	trace(evt.target);
    }
    

    This loadComplete function will be called when the target image is completely loaded. It will trace “Load Complete” to make sure that this function is invoked. It will also trace the type of the target (Loader).

    Now, to associate this COMPLETE event with the Loader, we shall modify the constructor method in our code like so:

    
    
    public function MyLoader() {
    
    	myURL = "MyImage.png";
    
    	loader = new Loader();
    	addChildAt(loader,0);
    
    	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
    
    	loadButton.addEventListener(MouseEvent.CLICK, loadAsset, false, 0, true);
    }
    

    Test the movie and press the “Start Loading” button.

    The output window will show the results, like so:

    Load Complete

    [object LoaderInfo]

    It returns LoaderInfo object as a target. So, we can say that, contentLoaderInfo utilizes the LoaderInfo object.

    What is loaderInfo?

    So, let us experiment more.

    Modify the loadComplete method like so:

    
    
    private function loadComplete(evt:Event):void
    {
    	trace("contentLoaderInfo:" + loader.contentLoaderInfo.height);
    	trace("loaderInfo:" + loader.loaderInfo.height);
    }
    

    Test the movie and press “Start Loading” button.

    The output window will show the result like so:

    contentLoaderInfo:600

    loaderInfo:640

    Here, contentLoaderInfo returned the height (600) of the target image.

    And, loaderInfo returned the height (640) of the main (root) SWF.

    If you want to experiment more, replace “height” property with “url”

    This will make loaderInfo give the information about root SWF and contentLoaderInfo give the information about the content being loaded by the Loader object. But both utilize the LoaderInfo object.

    OK, now we know how to associate the loading events using contentLoaderInfo with loader object. Next we shall start exploring all those events one by one in the proper sequence.


    Step 9: Which Events to Use?

    We already have discussed the required events in Step 3. But, I am listing them again, just for a revision.

    • IOErrorEvent.IO_ERROR
    • Event.OPEN
    • ProgressEvent.PROGRESS
    • Event.INIT
    • HTTPStatusEvent.HTTP_STATUS
    • Event.COMPLETE

    In the previous step, we used Event.COMPLETE. But remember, this is the last event to be fired, so we must track other events before Event.COMPLETE.

    Also, while loading an image there is no need to track all the above events.

    Loading an image (locally) will require just these events:

    • IOErrorEvent.IO_ERROR
    • ProgressEvent.PROGRESS
    • Event.COMPLETE or Event.INIT

    If image is loaded remotely (via HTTP request) add HTTPStatusEvent.HTTP_STATUS to the above list.

    But, for our example, we shall track all above events for the sake of learning. Also, you can any time change the URL to load a SWF – because, most of the time, tracking the loading process of a SWF requires all these events.

    So, let us start with IOErrorEvent.IO_ERROR.


    Step 10: IOErrorEvent.IO_ERROR

    To track IOErrorEvent.IO_ERROR, first add an import statement like so:

    
    
    import flash.events.IOErrorEvent;
    

    We shall add a new method loadError like so:

    
    
    private function loadError(evt:IOErrorEvent):void
    {
    	monitor.errorEventTF.text = "URL: '" + myURL + "' not found";
    }
    

    In case the target image is not found, then IOErrorEvent will be triggered. The above loadError method will be invoked. This method will display a message about the URL in the dynamic textfield named “errorEventTF” which is inside the “monitor” MovieClip, already placed on the stage.

    Monitor Window

    We shall also modify the constructor method to associate it with the loader object.

    
    
    public function MyLoader() {
    
    	myURL = "MyImage.png";
    
    	loader = new Loader();
    	addChildAt(loader,0);
    
    	loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadError);
    	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
    
    	loadButton.addEventListener(MouseEvent.CLICK, loadAsset, false, 0, true);
    }
    

    To test the IOError status, put an incorrect url (e.g. myURL = "MyImage1.png").

    Test the movie and click “Start Loading” button to see the status of IOError event. The monitor is displaying the incorrect URL.


    Step 11: Event.OPEN

    To track Event.OPEN, we shall add a new method loadStart() like so:

    
    
    private function loadStart(evt:Event):void
    {
    	monitor.openEventTF.text = String("Path opened");
    }
    

    We shall also modify the constructor method to associate it with the loader object.

    
    
    public function MyLoader() {
    
    	myURL = "MyImage.png";
    
    	loader = new Loader();
    	addChildAt(loader,0);
    
    	loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadError);
    	loader.contentLoaderInfo.addEventListener(Event.OPEN, loadStart);
    	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
    
    	loadButton.addEventListener(MouseEvent.CLICK, loadAsset, false, 0, true);
    }
    

    Test the movie and click “Start Loading” button to see the status of OPEN event.


    Step 12: ProgressEvent.PROGRESS

    We shall track loading progress of target image by updating the total number of bytes currently loaded.

    To track ProgressEvent.PROGRESS event, first we shall add a new variable totBytesLoaded like so:

    
    
    private var totBytesLoaded:Number;
    

    Then, add import statement for ProgressEvent Class like so:

    
    
    import flash.events.ProgressEvent;
    

    Now, we shall add a new method loadProgress like so:

    
    
    private function loadProgress(evt:ProgressEvent):void
    {
    	totBytesLoaded = Math.ceil(evt.bytesLoaded / 1024);
    	monitor.progressEventTF.text = "Bytes loaded :" + String(totBytesLoaded) + "kb";
    }
    

    We shall also modify the constructor method to associate it with the loader object.

    
    
    public function MyLoader() {
    
    	myURL = "MyImage.png";
    
    	loader = new Loader();
    	addChildAt(loader,0);
    
    	loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadError);
    	loader.contentLoaderInfo.addEventListener(Event.OPEN, loadStart);
    	loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
    	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
    
    	loadButton.addEventListener(MouseEvent.CLICK, loadAsset, false, 0, true);
    }
    

    Test the movie and click “Start Loading” button to see the status of PROGRESS event.

    You might not see any visible load progress, since we are loading the target image locally. But, if it is going to be loaded remotely then you will have a visible loading progress.

    You can still check the same local image, as if it is being loaded remotely. But, How?.

    In Flash IDE test player, there is an option “Simulate Download”. This option must be checked to see how the download progress will look like for the same local image. This is just a simulation. It will give you only a rough idea about progress.

    You can also simulate various connection speeds under “Download Settings”, available below “Simulate Download”.

    Simulate Download

    Once “Simulate Download” is checked, click the “Start Loading” button. Now you will have the visible loading progress. Observe the “Progress” reading in our monitor window.

    You can also add a progress bar for visual appearance of a loading progress.

    I have not added a progress bar, but if you wish to add it, then here are some lines to add a progress bar.

    Before coding for progress bar, drag the ProgressBar component from the Component panel to the Library to make it available for us.

    After that, add import statement for ProgressBar like so:

    import fl.controls.ProgressBar;

    Then, declare a var to hold progress bar like so:

    var myProgressBar:ProgressBar;

    Now, instantiate it and specify a source as contentLoaderInfo of a loader object like so:

    myProgressBar = new ProgressBar();

    myProgressBar.source = loader.contentLoaderInfo;

    myProgressBar.x = stage.stageWidth/2 - myProgressBar.width/2;

    myProgressBar.y = stage.stageHeight/2 - myProgressBar.height/2;

    addChild(myProgressBar);

    You can add these lines inside constructor method or you can create your own method and call it inside a constructor method.

    Do not forget to remove this progress bar inside loadComplete method like so:

    removeChild(myProgressBar);


    Step 13: Event.INIT

    To track Event.INIT event, we shall add a new method initialised() like so:

    
    
    private function initialised(evt:Event):void
    {
    	monitor.initEventTF.text = String("Initialized");
    }
    

    We shall also modify the constructor method to associate it with loader object.

    
    
    public function MyLoader() {
    
    	myURL = "MyImage.png";
    
    	loader = new Loader();
    	addChildAt(loader,0);
    
    	loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadError);
    	loader.contentLoaderInfo.addEventListener(Event.OPEN, loadStart);
    	loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
    	loader.contentLoaderInfo.addEventListener(Event.INIT, initialised);
    	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
    
    	loadButton.addEventListener(MouseEvent.CLICK, loadAsset, false, 0, true);
    }
    

    Test the movie and click “Start Loading” button to see the status of INIT event.


    Step 14: HTTPStatusEvent.HTTP_STATUS

    This HTTPStatusEvent is not required for loading images locally. We can simply replace the local path with a remote URL to check the status of this event.

    For the sake of completeness, we shall associate this event, even for loading images locally (in which case it will return “0″ as a status code). Check Step 3 for more info on this event.

    To associate HTTPStatusEvent, add the import statement like so:

    
    
    import flash.events.HTTPStatusEvent;
    

    Add a new line inside constructor method like so:

    
    
    loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpConnect);
    

    Now, put the new function httpStatus like so:

    
    
    private function httpStatus(evt:HTTPStatusEvent):void
    {
    	monitor.httpEventTF.text = String(evt.status);
    }
    

    Test the movie and click on “Start Loading” button. The status will show “0″ since the target is local.

    Step 15: Event.COMPLETE

    Finally, it’s time for Event.COMPLETE event. We already have added this COMPLETE event in Step 8, while learning LoaderInfo and contentLoaderInfo.

    This is our destination. Treat this as an entry point for the code after loading is complete. Here you can start further processing.

    Important tasks can be done here are listed down,

    • Add the loader object to a display list.
    • Declare and/or assign values to required variables.
    • Call for a function responsible for further processing.
    • Add event listeners (e.g. ENTER_FRAME event).
    • Remove event listeners.

    Here, we shall modify the loadComplete() method by adding a line,

    addChildAt(loader,0);

    We already have added this line in a constructor method. But, instead of adding it in a constructor method, we must add it after the loading process is completed. This is a good practice.

    So, we shall modify the constructor method, by removing the statement addChildAt(loader,0);

    …to add the loaded image to the bottom of the display list.

    The modified constructor will look like so:

    
    
    public function MyLoader() {
    
    	myURL = "MyImage.png";
    
    	loader = new Loader();
    
    	loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadError);
    	loader.contentLoaderInfo.addEventListener(Event.OPEN, loadStart);
    	loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
    	loader.contentLoaderInfo.addEventListener(Event.INIT, initialised);
    	loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatus);
    	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
    
    	loadButton.addEventListener(MouseEvent.CLICK, loadAsset, false, 0, true);
    }
    

    Now, modify loadComplete method like so:

    
    
    private function loadComplete(evt:Event):void
    {
    	monitor.completeEventTF.text = String("Load Complete");
    	addChildAt(loader,0);
    }
    

    Test the movie and click on “Start Loading” button to see the status of COMPLETE event.

    Thus, we have the complete setup for monitoring the loading process of an image as well as SWF.

    Also, you can simply replace the address path to load an image or SWF from any accessible remote server.


    Step 16: Loading From Internet

    Now, we shall see how to load an image from internet. Of course you must have a working Internet connection.

    First, we shall change our myURL like so:

    
    
    myURL = "http://www.free-pictures-photos.com/architecture/house-5xl3.jpg&quot;;
    

    Test the movie and click on “Start Loading” button. It will take some time to load.

    Since, being “Test Player”, it allowed to load the target image over internet. But, if you run “SWF” outside Flash IDE, the Flash Player Security dialog box will tell you to go to Settings.

    Player Security Warning

    To prevent from this warning, we have two ways around it:

    1. Set “Access network only” for Local playback security under Publish Settings.

    Access Network Only

    2. If you want to keep “Access local files only” for Local playback security under Publish Settings and still want to load a target from internet, then, you need to register that SWF as “Trusted” file. To make it “Trusted“, run SWF outside Flash. Right click inside player and click on Global Settings from the context menu.

    Global Settings

    Then go to the “Advanced” tab and click “Trusted Location Settings”.

    Settings Manager Trusted Location Settings

    Click “Add” under “Trusted_Location_Settings”.

    Trusted Location Settings

    Now, under “Add Site”, click “Add File” and browse for this same SWF (i.e LoaderClassExample.swf). After specifying the path for this SWF, click on “Confirm” button.

    Add SWF as a Trusted Location

    Now close all boxes and re-open SWF. Click on “Start Loading” button and the loading is started successfully.

    If suitable, you can also create “Projector.exe” to avoid all above settings. Projectors are always registered as trusted files.

    So Why Doesn’t the Example Load?

    Editor’s note:

    You may be wondering why the example SWF (at the top of the page) doesn’t load the image when embedded in the page, but does load it when loaded in the browser directly.

    This is because we host our SWFs and images on a different domain to the tutorial; they’re on s3.com rather than tutsplus.com. When the SWF tries to load the image, it’s looking for it at http://active.tutsplus.com/tutorials/actionscript/MyImage.png, because it’s using a relative path to this page.

    However, the image is actually somewhere on s3.com, which means the SWF can’t find it. To get around this, we can use the SWF’s own loaderInfo.url property to find the URL of the actual SWF, and use this to construct a path to the image.

    (Alternatively, we could hard-code in an absolute path to the image, but that’s pretty inflexible.)

    For more info, take a look at Step 21 onwards of this tutorial.

    Conclusion:

    Friends, that’s it for now. In this tutorial we saw how to load assets (in our case, an image) and monitored the loading process. We saw various events along with contentLoaderInfo, loaderInfo, absolute/relative paths and LoaderContext. We also experimented with loading an image from internet.

    I hope you found this information helpful. Please add comments to improve it more.


  6. Michael James Williams says:
    December 10, 2011 at 12:07 am
    This entry is part 3 of 3 in the series HTML5 Avoider Game Tutorial

    So far, we’ve got a never-ending stream of enemies that our avatar must avoid; one touch, and it’s game over. But so what? Since there’s no way to track the player’s progress, they have no idea whether they did better in their latest round than they ever did before. In this tutorial, you’ll learn how to keep score, how to display it on the canvas, and how to let the player know when they’ve beaten their own records.


    Refresher

    In the first and second parts of this tutorial, we’ve covered a number of concepts: drawing images to the canvas, detecting mouse actions, using if and while statements, storing variables in arrays, and the idea of variable scope.

    You can download the source files from the series up to this point if you’d like to dive straight in here, though I recommend reading all parts in order.

    Our game’s JavaScript file initialises a bunch of variables (including two arrays to store enemy x- and y-coordinates) outside of all functions, so that their contents are available to all functions. It also contains a function called setUpGame() which is run when the player first clicks the canvas; this loads the images, starts listening for any mouse movements, and sets up a “tick” function to be run every 25 milliseconds.

    When the mouse is moved, we move the position of the avatar, as stored in two variables – one for the x-coordinate and one for the y-coordinate – but we don’t immediately redraw the avatar’s image at this new location; all redrawing is handled in the tick function.

    The tick function does four things:

    • There’s a one-in-twenty chance that it’ll add a new enemy by pushing new x- and y-coordinates onto the relevant arrays.
    • It increments the y-coordinates of each enemy by looping through that array.
    • It redraws the avatar and enemy images according to their current coordinates.
    • It checks for a collision between the avatar and each enemy, giving an alert if one occurs.

    All clear?


    Warm Up Challenge

    If it’s been a while since you read the second part of the series (or if you just want to check that you understand what’s going on), have a go at these little exercises. They’re completely optional and separate to the actual tutorial, so I recommend working on a copy of your project rather than the original. You can complete all of these exercises using only information from the series so far.

    Easy

    Swap the avatar and enemy images around so that the player controls a smiley face that’s avoiding the falling skulls.

    (How many different ways can you figure out how to do this? I can think of three, off the top of my head.)

    Medium

    At the moment, there’s a flat one-in-twenty chance that a new enemy will be created in any given tick. I want you to make it so that there’s a one-in-one chance on the first tick, a one-in-two chance on the second, a one-in-three chance on the third, and so on.

    To make this more challenging, do it in reverse: a one-in-1,000 chance on the first tick, a one-in-999 chance on the second, a one-in-998 chance on the third, and so on. (After the thousandth tick, make it a steady one-in-one chance.)

    Hard

    Rather than waiting for the enemies to appear one by one, have the game start with twenty enemies already on screen.

    To make this more challenging, make them spread out around the canvas, and don’t allow them to overlap the avatar or each other.


    Keeping Time

    What’s the simplest way to measure how well the player is doing this round? The easiest thing I can think of is to keep track of how long it’s been since they hit an enemy. And since hitting an enemy means game over, we only need to keep track of how long they’ve been playing.

    To do this, we’ll just create a variable, set it to 0 when the round starts, and increment it every tick. Let’s call this variable ticksSurvived. And think: since we need to access it over and over again, it needs to be defined outside of all the functions, at the top of the JS file:

    
    
    var enemyYPositions = [];	//empty square brackets means new empty array
    var enemyXPositions = [];
    var avatarX = 0;
    var avatarY = 0;
    var avatarImage;
    var enemyImage;
    var ticksSurvived = 0;
    

    Now, we’ll give handleTick() yet another task to do: increment ticksSurvived. Put this after the collision detection; after all, if the avatar hits an enemy, it hasn’t actually survived the tick:

    
    
    function handleTick() {
    
    	//...
    
    	currentEnemyNumber = 0;
    	while (currentEnemyNumber < numberOfEnemies) {
    		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
    			alert("You hit an enemy!");
    		}
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    
    	ticksSurvived = ticksSurvived + 1;
    }
    

    To display this, for now, we’ll just alter the alert that appears when the avatar hits an enemy:

    
    
    function handleTick() {
    
    	//...
    
    	currentEnemyNumber = 0;
    	while (currentEnemyNumber < numberOfEnemies) {
    		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
    			alert("You hit an enemy! Ticks survived: " + ticksSurvived);
    		}
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    
    	ticksSurvived = ticksSurvived + 1;
    }
    

    That’s a bit weird; we’ve used the + operator to add a string to a number. We can add another string to the end:

    
    
    function handleTick() {
    
    	//...
    
    	currentEnemyNumber = 0;
    	while (currentEnemyNumber < numberOfEnemies) {
    		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
    			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
    		}
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    
    	ticksSurvived = ticksSurvived + 1;
    }
    

    Maybe this doesn’t seem odd to you, but some programming languages hate this. JavaScript doesn’t care. It knows that "some" + "string" equals "somestring", and assumes that you want to treat ticksSurvived as a string in this situation.

    (Some things to try out:

    12 + 6
    "12" + "6"
    "12" + 6
    12 + "6"

    Do they all do what you expect them to do?)

    Anyway, let’s give this new code a try.

    HTML5 avoider game tutorial
    Click to try it out.

    Great!

    As before, when you click OK, the alert box appears again, because all it does is pause the ticks rather than actually stopping them. But note that the number in the box increases by one; this is proof that JavaScript doesn’t turn the number into a string permanently; it only uses it as a string for the purposes of adding it to another string.

    While we’re on the subject of this alert box: don’t you find it annoying?


    Try Again

    At the moment, the only way to start a new round is to refresh the page. Let’s make it easier and less irritating to have another go, by making the “OK” button on the alert box reset the game.

    Since the alert effectively pauses the game, whatever we put on the line after the alert will run once the player hits OK. Let’s make it call a new function, startNewGame():

    
    
    	currentEnemyNumber = 0;
    	while (currentEnemyNumber < numberOfEnemies) {
    		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
    			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
    			startNewGame();
    		}
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    

    So what do we need startNewGame() to do?

    Perhaps we should just call setUpGame() again – but no, nothing in that needs doing twice: we don’t need to load the images or add the mouse event listener or set up the ticks again.

    Have a think about what would be needed, and try out your ideas. My solution is below; take a look when you’re ready.

    
    
    function startNewGame() {
    	enemyXPositions = [];
    	enemyYPositions = [];
    	ticksSurvived = 0;
    }
    

    That’s all. You can do more if you wish, but this is the minimum required.

    Note that we don’t have to do anything with the canvas – we don’t need to clear it, or draw anything to it, or manipulate the images – because this is all done in handleTick(). We don’t have to go through all the elements in the arrays, one by one, either, because the arrays are simply a list of coordinates that we use to stamp the enemy images onto the canvas; the enemies don’t exist as actual objects.

    HTML5 avoider game tutorial
    Click to try it out.

    So this is great – the player can play the game over and over again to keep trying for a better score. Except… how do they know whether they’ve beaten their previous score? At the moment, they just have to remember they top score so far, or write it down. We can do better than that.


    Remember the Best Score

    How should we store the top score? In another variable, of course!

    
    
    var enemyYPositions = [];	//empty square brackets means new empty array
    var enemyXPositions = [];
    var avatarX = 0;
    var avatarY = 0;
    var avatarImage;
    var enemyImage;
    var ticksSurvived = 0;
    var mostTicksSurvived = 0;
    

    Naturally, it has to live outside of the functions; by now, I’m sure you understand why.

    To begin with, we set it to 0, of course – the player hasn’t even completed a round. When the avatar hits an enemy, let’s update the new score as required:

    
    
    	while (currentEnemyNumber < numberOfEnemies) {
    		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
    			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
    			if (ticksSurvived > mostTicksSurvived) {
    				mostTicksSurvived = ticksSurvived;
    			}
    			startNewGame();
    		}
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    

    Let’s also tell the player that they beat their old high score:

    
    
    	while (currentEnemyNumber < numberOfEnemies) {
    		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
    			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
    			if (ticksSurvived > mostTicksSurvived) {
    				alert("New high score!");
    				mostTicksSurvived = ticksSurvived;
    			}
    			startNewGame();
    		}
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    

    Take a look:

    HTML5 avoider game tutorial
    Click to try it out.

    Excellent. Now let’s give the player a little more information on how much better they did:

    
    
    	while (currentEnemyNumber < numberOfEnemies) {
    		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
    			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
    			if (ticksSurvived > mostTicksSurvived) {
    				alert("You beat your old high score by " + (ticksSurvived - mostTicksSurvived) + " ticks!");
    				mostTicksSurvived = ticksSurvived;
    			}
    			startNewGame();
    		}
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    

    Note here that ticksSurvived and mostTicksSurvived are treated as numbers when subtracting one from the other, but the resulting expression (ticksSurvived - mostTicksSurvived) is treated as a string when added to the other strings! This can get really confusing, if you’re not careful.

    HTML5 avoider game tutorial
    Click to try it out.

    All right, so now the player knows how well they were doing, after they get game over, we should give them an indication of how well they are doing, while they’re still playing.


    Drawing the Score to the Canvas

    It’s really easy to write text into a canvas – and no, we don’t need to piece it together from different images of different letters!

    Remember that to draw an image to the canvas we call canvas.getContext("2d").drawImage(). Writing text is very similar: we call canvas.getContext("2d").fillText().

    We must pass three arguments to fillText():

    • A string containing the text to write.
    • The x-coordinate at which to write it.
    • The y-coordinate at which to write it.

    There’s an optional fourth argument:

    • The maximum width that the text is allowed to take up on screen.

    …but we won’t worry about that for now.

    To test this out, head to handleTick(), find the line where we draw the avatar to the canvas, and draw a sample line of text just afterwards:

    
    
    	gameCanvas.width = 400;		//this erases the contents of the canvas
    	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
    	gameCanvas.getContext("2d").fillText("Testing, testing, one, two, three.", 100, 100);
    

    Try it out:

    HTML5 avoider game tutorial
    Click to try it out.

    Note that, since this gets drawn after the avatar and before the enemies, the enemies get drawn on top of it, while the avatar goes underneath:

    HTML5 avoider game tutorial
    Click to try it out.

    Like I say, the first argument required is a string, and – as we’ve seen – we can construct a string by adding a string to a number. So, this should work:

    
    
    	gameCanvas.width = 400;		//this erases the contents of the canvas
    	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 100, 100);
    

    …and indeed it does!

    HTML5 avoider game tutorial
    Click to try it out.

    But it’s a bit of a mess, floating there underneath the enemies with that tiny font. Let’s sort that out.


    Tidy Up the Text

    First, let’s move the text so that the enemies move underneath it. This just means drawing it after all of the enemies are drawn, so move the relevant line down:

    
    
    	gameCanvas.width = 400;		//this erases the contents of the canvas
    	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
    
    	currentEnemyNumber = 0;
    	while (currentEnemyNumber < numberOfEnemies) {
    		gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 100, 100);
    

    Now, let’s move it to the top-left of the screen. That’s, (0, 0) so this should work, right?

    
    
    	gameCanvas.width = 400;		//this erases the contents of the canvas
    	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
    
    	currentEnemyNumber = 0;
    	while (currentEnemyNumber < numberOfEnemies) {
    		gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 0);
    

    Hmm. Nope. We can’t see the score at all. This is because it’s using (0, 0) to place the bottom-left corner of the text. We need to move the text down a bit, then:

    
    
    	gameCanvas.width = 400;		//this erases the contents of the canvas
    	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
    
    	currentEnemyNumber = 0;
    	while (currentEnemyNumber < numberOfEnemies) {
    		gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);
    

    Check it out:

    HTML5 avoider game tutorial
    Click to try it out.

    Okay, so far so good. Now, let’s change the font itself. We do this by setting the canvas’s context’s font property to a CSS string representing the font. If you’re not familiar with CSS, don’t worry; at this stage, all you need to know is that it contains the font’s size and the fontface:

    
    
    	gameCanvas.width = 400;		//this erases the contents of the canvas
    	gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
    
    	currentEnemyNumber = 0;
    	while (currentEnemyNumber < numberOfEnemies) {
    		gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    
    	gameCanvas.getContext("2d").font = "10px Impact";
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);
    

    (“px” stands for “pixels”.)

    Note that we have to set the font before drawing the text!

    Take a look:

    HTML5 avoider game tutorial
    Click to try it out.

    It works – but the Impact font is really hard to read at that size. Let’s make it bigger:

    
    
    	gameCanvas.getContext("2d").font = "18px Impact";
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);
    
    HTML5 avoider game tutorial
    Click to try it out.

    Unfortunately, this doesn’t work so well, because the font is still 10px from the top of the canvas, but now it’s 16px tall!

    We could keep changing the y-position of the font to fix this, but there’s an alternative: we’ll make it so that the position we specify determines the top-left corner of the text, rather than the bottom-left corner. It’s easy:

    
    
    	gameCanvas.getContext("2d").font = "18px Impact";
    	gameCanvas.getContext("2d").textBaseline = "top";
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);
    

    Of course, now, there’s a 10px gap between the top of the text and the top of the canvas:

    HTML5 avoider game tutorial
    Click to try it out.

    …but that’s easy to fix now:

    
    
    	gameCanvas.getContext("2d").font = "18px Impact";
    	gameCanvas.getContext("2d").textBaseline = "top";
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 0);
    

    Well, actually, I like a bit of padding, so let’s do this:

    
    
    	gameCanvas.getContext("2d").font = "18px Impact";
    	gameCanvas.getContext("2d").textBaseline = "top";
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 5, 5);
    
    HTML5 avoider game tutorial
    Click to try it out.

    Much better.

    Different Fonts

    Perhaps you’re wondering whether there’s a list of fonts we can use. Well, yes and no. See, if you pick a font that the player doesn’t have installed on their computer, then the text will just be displayed in the default font. Remember, JavaScript is drawing the text on the fly, using the player’s computer’s resources.

    We’re fine using Impact, because it’s installed on every computer – but does that mean we can’t use any font other than the few in this list?

    Fortunately, no. We can use any font we like, as long as we give the user access to it somehow. And for this, we’re going to use that CSS file – you know, the one we haven’t touched since the start of the series.

    Suppose we have a font called “Really-Awesome”. This will exist on your computer, somewhere, as a file – probably a .TFF file (“True Type Font”). Let’s suppose that file is called ReallyAwesomeFont.ttf.

    Now suppose you upload this font to your website – reallyawesomewebsite.com – so that there’s a direct URL to it: http://reallyawesomewebsite.com/fonts/ReallyAwesomeFont.ttf.

    You can then let the player’s browser know about it by adding this to your CSS file:

    
    
    @font-face {
        font-family: 'Really-Awesome';
        src: url('http://reallyawesomewebsite.com/fonts/ReallyAwesomeFont.ttf');
    }
    

    With this line in your CSS, you can alter your code like so:

    
    
    	gameCanvas.getContext("2d").font = "18px Really-Awesome";
    	gameCanvas.getContext("2d").textBaseline = "top";
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 5, 5);
    

    …and it’ll work, because their browser will look up the “Really-Awesome” font in the stylesheet, and find the URL to the TTF. Great!

    I’m not going to demonstrate this because I don’t own the redistribution rights to any fonts; if I upload some and give you the link to the TTF as part of this tutorial, that’s not really fair. But there is an alternative…

    Google Web Fonts

    Google has assembled a large collection of fonts that you can use in your project in your CSS, using a similar principle as above. Take a look at the collection.

    There are a few criteria by which you can search for fonts, and you can enter some sample text to see how it’ll be displayed:

    HTML5 avoider game tutorial
    Google Web Fonts.

    I’m going to choose Iceland. When I click Quick Use, it gives me this HTML:

    
    
    <link href='http://fonts.googleapis.com/css?family=Iceland' rel='stylesheet' type='text/css'>
    

    If you load http://fonts.googleapis.com/css?family=Iceland in your browser, you’ll see that it’s the same kind of thing as we wrote from scratch before:

    
    
    @media screen {
    @font-face {
      font-family: 'Iceland';
      font-style: normal;
      font-weight: 400;
      src: local('Iceland'), local('Iceland-Regular'), url('http://themes.googleusercontent.com/static/fonts/iceland/v1/F6LYTZLHrG9BNYXRjU7RSw.woff') format('woff');
    }
    }
    

    It has a few more details, and the font is in WOFF format rather than TTF, but you get the idea.

    You can use whichever font you like (and it doesn’t have to be a Google Web Font), but for the purpose of this tutorial I’m going to assume that you’re using Iceland. So, edit game.html and paste the font reference into it:

    
    
    <!DOCTYPE html>
    <html>
    	<head>
    		<title>HTML5 Avoider Game</title>
    		<script src="js/main.js"></script>
    		<link rel="stylesheet" href="css/style.css" />
    		<link href='http://fonts.googleapis.com/css?family=Iceland' rel='stylesheet' type='text/css'>
    	</head>
    	<body>
    		<canvas id="gameCanvas" onclick="setUpGame();" width="400" height="300"></canvas>
    		<p>Click inside the box to play. Warning: extremely basic!</p>
    		<p>Make sure you have <a href="http://google.com/chrome/&quot; rel="external">Chrome</a>.</p>
    		<p>From <a href="http://active.tutsplus.com/tutorials/html5/html5-avoider-game-tutorial-keeping-score">HTML5 Avoider Game Tutorial: Keeping Score</a>.</p>
    	</body>
    </html>
    

    Now, back in main.js, change the font from Impact to Iceland:

    
    
    	gameCanvas.getContext("2d").font = "18px Iceland";
    	gameCanvas.getContext("2d").textBaseline = "top";
    	gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 5, 5);
    

    Take a look:

    HTML5 avoider game tutorial
    Click to try it out.

    Cool!

    Challenge: Show the Best Score

    Now that the current score is on screen at all times, it’s only natural that the player will want to see what they’re trying to beat.

    Using what you’ve learnt, draw their best score at the top-right of the canvas. This is a little trickier than it seems: you’ll have to decide what to do (if anything) when the current score overtakes the current top score!


    Saving Scores Between Sessions

    You’ve probably noticed by now that the high score is reset when you reload the page. This makes sense – after all, we run this line right at the start:

    
    
    var mostTicksSurvived = 0;
    

    …but even without that line, the high score still wouldn’t persist. All variables get reset and unassigned when you leave the page.

    However, there is an alternative: every browser sets aside 5MB of storage for each web site domain. You can store any string you like in this 5MB storage, and it’ll stay there even if the user closes their browser and restarts their computer.

    It’s called local storage, and it’s really easy to use! To save something to it, you just need to give it two strings:

    • a name for the item, and
    • the value of the item.

    To retrieve it, you just need the name that you originally used.

    A Quick Example

    Here’s a quick example: let’s add something to the local storage right at the start of the setUpGame() function:

    
    
    function setUpGame() {
    	localStorage.setItem("exampleItem", "This is a great example.");
    

    Save the file, and load your game. Then close the tab.

    Now, edit your JS file again, delete the line you just added, and replace it with a line that should retrieve the item:

    
    
    function setUpGame() {
    	alert(localStorage.getItem("exampleItem"));
    

    So, just to be clear, there is now nothing in the code that sets the value of "exampleItem".

    When you load the game this time, you should see an alert with "This is a great example." – proof that the string has been saved between sessions.

    We can remove this item from the local storage using localStorage.removeItem():

    
    
    function setUpGame() {
    	localStorage.removeItem("exampleItem");
    

    I recommend you do this now, and then delete the line entirely.

    You can also clear everything in the local storage at once, using localStorage.clear() (no arguments required). Okay – not quite everything. Your page can only affect the local storage space assigned to the domain on which it is hosted; I can’t clear your local storage for google.com from a page hosted at tutsplus.com, and vice-versa.

    Saving the Best Score

    Now that we’ve seen an example, let’s put it into practice.

    Whenever a new high score is set, let’s save it to the local storage. It only gets set in one place: when the avatar collides with an enemy and the current score is higher than the best score. So, add the call to localStorage.setItem() in the appropriate place:

    
    
    	while (currentEnemyNumber < numberOfEnemies) {
    		if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
    			alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
    			if (ticksSurvived > mostTicksSurvived) {
    				alert("You beat your old high score by " + (ticksSurvived - mostTicksSurvived) + " ticks!");
    				mostTicksSurvived = ticksSurvived;
    				localStorage.setItem("bestScore", mostTicksSurvived);
    			}
    			startNewGame();
    		}
    		currentEnemyNumber = currentEnemyNumber + 1;
    	}
    

    When the page is first loaded, we should check to see whether there already is a high score saved in the local storage, and assign mostTicksSurvived to that value, if so. (You don’t need to repeat this check once the page is loaded, unless you’re worried about the user playing the game in two separate tabs at once.)

    How do we check whether a value exists? All we have to do is put it inside an if condition:

    
    
    if (localStorage.getItem("thisItemDoesNotExist")) {
    	alert("This alert will never appear!");
    }
    

    The alert() above never gets called because localStorage.getItem("thisItemDoesNotExist") does not exist. Easy, right? So at the start of setUpGame(), we can just write:

    
    
    function setUpGame() {
    	if (localStorage.getItem("bestScore")) {
    		mostTicksSurvived = localStorage.getItem("bestScore");
    	}
    

    Have a go. Load the page, set a high score, then beat it. Reload the page, then get a lower score – does it tell you you beat your old score?

    HTML5 avoider game tutorial
    Click to try it out.

    Great! By the way, if you took the challenge earlier then you’ll be able to see your previous best score in the top-right corner of the canvas, and this will now carry over from session to session.


    Sidenote: Strong and Weak Typing

    We’re about done for this part of the series, but I just want to point out that, once again, we’ve been treating a string as a number and a number as a string: local storage only saves string values, yet we save a number to it when we save the best score, and use the value we retrieve from it as a number later on.

    This is acceptable, because JavaScript is what’s called “weakly-typed”. Other programming languages are “strongly-typed”, which means that if you say that something is a number, then it stays a number; if you say something is a string, then it stays a string.

    In a strongly-typed language, if you want to add the string "Score: " to the number 32, then you have to explicitly tell the language to treat 32 as a string, perhaps like so:

    "Score: " + (32 as String)

    Also, in a strongly-typed language, when you define a variable, you also specify what type it is:

    
    
    var greeting:String = "Hello.";
    var score:Number = 1000;
    

    But JavaScript doesn’t worry about these things. This doesn’t make it better or worse than a strongly-typed language, just different.


    Wrapping Up

    That’s it for this part of the tutorial. Now your game has both a game over condition and a means of keeping score. Plus, you learned about drawing text to a canvas, choosing fonts, and using the local storage.

    If you’d like to challenge yourself before the next part, have a go at making these changes:

    • Easy: Draw the best score on the canvas, before the player clicks it.
    • Medium: Store the player’s top five scores.
    • Hard: Save the positions of all the enemies to local storage, and restore them in the next session (you may have to do extra research here! Hint: look into JSON.)

    Enjoy!


  7. ActiveToFocus says:
    December 10, 2011 at 12:58 am

    Here’s a handy tool you can use to create tweens without having to guess all the numbers involved. Just click and drag to create the graph of the tween, tweak your desired timing, and export to any of four formats: Flash’s native tweening engine, Tweener, TweenLite, or TweenMax. And if you’re a Tuts+ Premium member, you can grab the source code for the tool itself!


    Use Easer

    Easer is simple to use:

    1. Click the Time button to set the easing time.
    2. Click the red line to add a custom node. You can drag the control points left or right to adjust the curve for the ease transition. You also can delete node by pressing Delete on your keyboard.
    3. Click Preview button to view your custom ease transition.
    4. Pick your tween engine of choice, then click “COPY CODE” button.
    5. Paste the code into your project’s source. Make sure you import the Easer class from the source download.

    Example Code

    
    
    import com.activetofocus.easer.Easer;
    import caurina.transitions.Tweener;
    
    var easerArr:Array = [{Nx:69,My:0,Ny:-263,Mx:0},{Nx:360,My:-210,Ny:-8.5,Mx:183},{Nx:442,My:-135,Ny:-259,Mx:397},{My:-200,Mx:520}];
    
    Tweener.addTween(mc,{y:29, time:2, transition:Easer.to(easerArr)});
    

    Get Easer’s Source

    The download link at the top of this page is for the files required to use Easer. If you’d like to modify Easer, or just take it apart to see how it works, then you can get the source files for Easer itself from Tuts+ Premium.


  8. David Appleyard says:
    December 10, 2011 at 1:02 am

    Each month, we bring together a selection of the best tutorials and articles from across the whole Tuts+ network. Whether you’d like to read the top posts from your favourite site, or would like to start learning something completely new, this is the best place to start!


    Huge Improvements to Tuts+ Premium

    As many of you know, Tuts+ is accompanied by an online educational membership called Tuts+ Premium. We’re very excited to announce that the membership has received a huge upgrade, including a new library of courses, 27 top-selling educational eBooks, member forums, and a completely redesigned UI.

    You can check out all the changes here, and find out about all the fantastic new content available!

    Our new premium website is a drastic improvement over the old system. It includes a slick and polished user interface and presents all of our tutorials the way that you would expect, from within your browser. We are now providing courses and ebooks from within Tuts+ Premium to make it even more valuable. So what are you waiting for? Head over to the new Tuts+ Premium site and let us know what you think.

    Take a Tour of Tuts+ Premium


      Psdtuts+ — Photoshop Tutorials

    • Create Detailed Vintage Typography with Illustrator and Photoshop

      Create Detailed Vintage Typography with Illustrator and Photoshop

      In this tutorial we will demonstrate how to customize a typeface in Illustrator and then use Photoshop to create a stunning vintage detailed typographic design. Let’s get started!

      Visit Article

    • Realistic Portrait Retouching With Photoshop

      Realistic Portrait Retouching With Photoshop

      Today’s designers and photographers need to have a varied skill set that sets them apart from the pack. One common skill that both can use is portrait photography retouching. This tutorial will make you a more effective retoucher and help keep your portraits looking clean and realistic. Subtlety is – going too far will only make the results noticeable. The best comment you can get after presenting a final image is "I didn’t even notice you did that". Let’s get started!

      Visit Article

    • How to Paint Clouds With Photoshop

      How to Paint Clouds With Photoshop

      Photoshop is an excellent tool for manipulating photographs but it can also be used as a means to create stunning digital art. This tutorial is part of a 25-part video tutorial series demonstrating everything you will need to know to start producing digital art in Photoshop. Digital Art for Beginners, by Adobe Certified Expert and Instructor, Martin Perhiniak will begin by teaching you how to draw in Photoshop. At the conclusion of this series you will know all you need to produce your own concept art and matte paintings in Photoshop.

      Visit Article


    • Nettuts+ — Web Development Tutorials

    • How to Create a Sublime Text 2 Plugin

      How to Create a Sublime Text 2 Plugin

      Sublime Text 2 is a highly customizable text editor that has been increasingly capturing the attention of coders looking for a tool that is powerful, fast and modern. Today, we’re going to recreate my popular Sublime plugin that sends CSS through the Nettuts+ Prefixr API for easy cross-browser CSS.

      Visit Article

    • 30 Days to Learn HTML and CSS: a Free Tuts+ Premium Course

      30 Days to Learn HTML and CSS: a Free Tuts+ Premium Course

      If you’ve ever wanted to learn how to build websites and web apps, HTML and CSS are the first skills you should learn. They are so fundamental that we believe everyone has the right to learn these skills for free.

      Visit Article

    • Dig into Dojo

      Dig into Dojo

      Maybe you saw that tweet: “jQuery is a gateway drug. It leads to full-on JavaScript usage.” Part of that addiction, I contend, is learning other JavaScript frameworks. And that’s what this four-part series on the incredible Dojo Toolkit is all about: taking you to the next level of your JavaScript addiction.

      Visit Article


    • Vectortuts+ — Illustrator Tutorials

    • How to Create a Vector Stamp Set in Illustrator

      How to Create a Vector Stamp Set in Illustrator

      In the following tutorial you will learn how to create a vintage, vector stamp set in Adobe Illustrator. Learn how to build a stamp illustration, shape by shape. We’ll construct the stamp border vector shape, highlight the edges, create the branding, and give the vector postage stamp a vintage texture, and final illustrator stamp effect. Let’s get started with making this vector stamp in Illustrator and then transform this into a vector stamp set.

      Visit Article

    • Create a Vector Bamboo Forest with Blends, Brushes and Profiles

      Create a Vector Bamboo Forest with Blends, Brushes and Profiles

      In today’s tutorial you’ll learn how to create a bamboo vector illustration with the help of custom art and pattern brushes, blends and profiles on strokes in Adobe Illustrator CS5. Vector bamboo is an excellent element to use in your work to give a classic Japanese fine art print feel, for use as bamboo forest art background in a larger illustration, and to make your vector pictures stand out with stylish bamboo art. So let’s jump straight into it!

      Visit Article

    • Massive Collection of Vintage Vector Graphics: Floral Borders, Corners, and Frames

      Massive Collection of Vintage Vector Graphics: Floral Borders, Corners, and Frames

      Welcome design rockstar, today you’re in for a real treat. We have a massive collection of vector graphics compiled for free download today. We’ve assembled vintage vector floral graphics that have antique floral borders, classic ornate corners, and decorative frames.

      Visit Article


    • Webdesigntuts+ — Web Design Tutorials

    • Bring Your Forms Up to Date With CSS3 and HTML5 Validation

      Bring Your Forms Up to Date With CSS3 and HTML5 Validation

      Let’s look at how to create a functional form which validates users’ data, client-side. With that done, we’ll cover prettying it up using CSS, including some CSS3!

      Visit Article

    • Design a Clean Launch Email for a Mobile App

      Design a Clean Launch Email for a Mobile App

      During this tutorial we’ll be using Adobe Photoshop to create a unique and clean email, announcing the launch of a new mobile app. We’ll look at using smart objects, clipping masks, warping text, and even examine the psychology of our users.

      Visit Article

    • Financial Best Practices for Web Design Freelancers

      Financial Best Practices for Web Design Freelancers

      A lot of web designers start their careers as employees for larger design firms. However, it seems inevitable that most designers will at least consider going out on their own as freelancers, either for side jobs or full time. One major key to any successful freelancing career, though, is to stay on top of your finances.

      Visit Article


    • Phototuts+ — Photography Tutorials

    • 50 Amazing Animal Photos

      Amazing Animal Photos

      Animals are, without a shadow of a doubt, a fascinating photography subject. They’re at their most intriguing when they’re unpredictable and wild, allowing you to capture something of their very nature. This collection is a look at some outstanding shots of animals, of every kind, in the hope that it inspires and encourages you in your endeavors to immortalize something of the creatures with which we share our existence.

      Visit Article

    • The Best Way To Learn Sports Photography

      The Best Way To Learn Sports Photography

      Whether you’re a sports fan or not, it’s hard to deny the huge popularity of sports in modern culture. In today’s tutorial, instead of giving you tips about directly shooting sports, we’re focusing on giving you tips on learning how to shoot it. We hope you enjoy this new approach.

      Visit Article

    • The Camera Swap Survival Guide

      The Camera Swap Survival Guide

      In photography circles, you run into two types of people. Those who love their gear and those who would just as soon forget about. I love making photographs, but I also love cameras and the other gear used in the process. Therefore, I love camera swaps and flea markets. The variety of tools available for our craft is astounding and frankly overwhelming. But I’m here to help. I’ve been going to swaps for 12 years. I’ve been ripped off more times than I care to admit, but after all this time, I’m finding more treasure than fool’s gold. So today, I’ll guide you through the jungle that is the camera swap.

      Visit Article


    • Cgtuts+ — Computer Graphics Tutorials

    • Facial Animation With Morph Targets In Cinema 4D, Part 1 – Cg Premium Content

      Facial Animation With Morph Targets In Cinema 4D, Part 1 – Cg Premium Content

      In this new two part Premium tutorial, Aleksey Voznesenski will give you an introduction to mesh animation in Cinema 4D, in this case a face with the use of the pose morph tag. We’ll also actually model the character, add materials, do some lighting, Faking GI is always fun, and then animate the little bugger.

      Visit Article

    • Making Of: The Abandoned Lobby in Maya and Mentalray, A Lighting & Rendering Overview

      Making Of: The Abandoned Lobby in Maya and Mentalray, A Lighting & Rendering Overview

      In this overview tutorial, author Pratik Gulati will give you valuable insight into Lighting and Rendering a scene in Maya using Mentalray. Using his “Abandoned Backyard Lobby” image as a basis, Pratik will discuss how he approached the Lighting setup and walk you through the render settings for achieving a very realistically lit interior scene with Mentalray.

      Visit Article

    • Quick Tip: Creating A Simple 3D Puzzle In Maya

      Quick Tip: Creating A Simple 3D Puzzle In Maya

      In this quick tip, author Abed Ibrahim will show you a great way to create a simple 3D puzzle in Maya. Although simple in approach, this valuable technique can be used in a variety of projects, ranging from very simple puzzles to extremely complex scenes, or even animations.

      Visit Article


    • Aetuts+ — After Effects Tutorials

    • Design A Fantastic Floating Card Logo Reveal – AE Premium

      Design A Fantastic Floating Card Logo Reveal – AE Premium

      In this tutorial we’ll break down a project I created called Motion Cards. We’ll create 3 scene’s in which we’ll animate some falling customizable placeholders that will be re purposed using Trapcode Particular for a dynamic logo reveal.

      Visit Article

    • Regenerate Like A “Time Lord” From Dr. Who

      Regenerate Like A “Time Lord” From Dr. Who

      In this tutorial, we’ll be creating a regeneration effect, inspired by the Doctor Who TV show. I say inspired by, because it’s not screen-accurate, but we’ll be using AE’s built-in tools, alongside some stock footage, VCP’s Optical Flares and Trapcode Particular to pull off a pretty convincing regeneration.

      Visit Article

    • An Apple Box At Its Core

      An Apple Box At Its Core

      In today’s video, I’ll talk about the Apple Box… a rectangular multi-purpose block used on production sets dating back to practically the beginning of film. This video is for exposure more than anything. A year ago, I didn’t even realize those boxes had a name, and now I end up pretty much using them at least once on every shoot I do. Hope you enjoy it. :)

      Visit Article


    • Audiotuts+ — Audio & Production Tutorials

    • Why You Should Use Metering Tools while Mixing and Mastering

      Why You Should Use Metering Tools while Mixing and Mastering

      Last AES convention I met a manufacturing rep for a very prestigious equipment company. He was demoing a piece of equipment for me, showing me all the great knobs and buttons that it had to offer. Then he said something along the lines of, ’We don’t include a screen for these things since you’re supposed to mix with your ears.” That’s when I took my exit stage left. I think imposing a viewpoint like that is just plain wrong.

      Obviously, you’re supposed to mix with your ears, but I don’t think looking at meters is going to destroy your mix.

      Visit Article

    • Adding Flavor to Chords -

      Adding Flavor to Chords -” Sixth Chords -” Basix

      Today we are going to cover how to add some flavor to your chords and compositions using sixths in both major and minor. Just like the 7ths chord tutorial, we will approach this chord concept from the ground up and look it from all possible angles. If you have heard of these types of chords but never knew exactly how they were constructed then this tutorial is for you. We will cover everything from basic structure to different voicings of the chords and try to apply them in a creative context. The sixth chords are waiting, you ready?

      Visit Article

    • 20 Podcasts that Musicians Should Subscribe To (And Why!)

      Podcasts that Musicians Should Subscribe To (And Why!)

      Rather than listening to music as I drive, shave and garden, I regularly listen to podcasts. That way Im not just being entertained, but educated as well. In this post we introduce you to the Top 20 podcasts musicians should subscribe to.

      A podcast is like a radio show, only distributed via RSS over the internet. Some are professionally produced, but many are done by amateurs. Most are about a particular interest or topic. And there are a ton of them on music and recording -” some featuring indie music, others exploring music technology, and many explaining techniques for playing and recording music. In this article we’ll focus on the podcasts that teach you about producing music, and not the ones that help you discover new music. Maybe we’ll cover those in a future post.

      Visit Article


    • Activetuts+ — Flash, Flex & ActionScript Tutorials

    • TimelineLite Ultimate Starter Guide: Introduction

      TimelineLite Ultimate Starter Guide: Introduction

      TimelineLite is the ultimate tool for creating elaborate and precise sequences of scripted animation. It is an integral part of the GreenSock Tweening Platform that allows you to make the most of TweenLite and TweenMax. This series of screencasts will walk you step by step through everything you need to know to take your AS3 tweening skills to the next level.

      Visit Article

    • Getting Started With Scoreoid

      Getting Started With Scoreoid

      Games are becoming ever more popular, especially casual games on mobile devices and tablets. In these games, the importance of leaderboards is multiplied – and game developers need a simple cross-platform solution for this. In this tutorial we will cover Scoreoid and how it can help you with game development.

      Visit Article

    • Effectively Organize Your Game’s Development With a Game Design Document

      Effectively Organize Your Game’s Development With a Game Design Document

      Have you ever dived right in to developing a game, but found yourself having to constantly change aspects of the design or the gameplay due to a lack of planning? You should consider using a game design document: a guiding vision of the game as a whole, pulling together ideas and plans for the design, development, and business sides of your game.

      Visit Article


    • Wptuts+ — WordPress Tutorials

    • 5 Cardinal Sins of WordPress Theme Development

      Cardinal Sins of WordPress Theme Development

      We talk alot on this site about tips and tricks for getting what you want out of WordPress… but today we’re going to take a step back from the technical stuff to look at some practices, bad habits, and coding faux pas that would be better left in our past. So, forgive the heavy-handed post title (haha!), we’re about talk bring up 5 surprisingly common practices that are blemishes on the platform.

      Visit Article

    • DIY WordPress Framework Part 4: Using the Framework as a Boiler Plate

      DIY WordPress Framework Part 4: Using the Framework as a Boiler Plate

      Last time we used our framework as a child theme, creating a totally new theme that depends on the framework. Today we’re going to use our framework as a boilerplate, copying the folder and making edits right to it.

      Visit Article

    • WordPress Monthly News: November 2011

      WordPress Monthly News: November 2011

      For some, WordPress is a livelihood whereas, for others, it’s just for fun. Nonetheless, anyone involved with WordPress needs to stay on track with the latest developments in the blogging world. This is our monthly article covering the latest developments in the WordPress world from news to the latest new kick-ass themes on our marketplaces.

      Visit Article


    • Mobiletuts+ — Mobile Development Tutorials

    • jQuery Mobile 1.0

      jQuery Mobile 1.0

      The official release of jQuery Mobile 1.0 was recently announced, and this tutorial will provide you with an overview of how this popular framework can assist you in your cross-platform and web based app development!

      Visit Article

    • Building a Caterpillar Game with Cocos2D

      Building a Caterpillar Game with Cocos2D

      In this series, we will be recreating the popular Atari game Centipede using the Cocos2D game engine for iOS. Centipede was originally developed for Atari and released on the Arcade in 1980. Since then, it has been ported to just about every platform imaginable. For our purposes, we will be calling the game Caterpillar.

      Visit Article

    • Android SDK: Using the Text to Speech Engine

      Android SDK: Using the Text to Speech Engine

      This tutorial will teach you to give your applications a voice with the Android SDK text to speech engine!

      Visit Article


    • FreelanceSwitch — Articles and Resources for Freelancers

    • 10 Free Apps for Working with Video

      10 Free Apps for Working with Video

      Video has become a must-have for every website or blog aiming to enhance its presence online. It’s a common practice that video-related orders are often assigned to freelancers, and these are not only simple video editing tasks, but the preparation of how-to’s, demos, screencasts, video embedding and distribution as well.

      Here is a roundup of the most popular video software and services recommended for freelancers’ everyday use.

      Visit Article

    • 30 Top Facebook Apps for Business

      30 Top Facebook Apps for Business

      Facebook is a good place to communicate with friends and get new job offers. Freelancers should not miss an employment opportunity on Facebook. The social network app section is a real treasure box with multiple handy applications.

      These are some of the best Facebook applications that help freelances boost their productivity, enhance their business pages, show off their portfolio and attract new contacts. Since many freelancers work with social media as experts, account managers and analysts, the list below has both apps for personal profiles and Facebook pages.

      Visit Article

    • The Latest Google Update is Fantastic News for Freelance Writers

      The Latest Google Update is Fantastic News for Freelance Writers

      On November 3, 2011 Google published a new article on their blog informing readers that fresh new content is now being seen as highly valuable on their blog or website. This “freshness update” is a new addition to Google’s “Caffeine web indexing system”.

      Now blog owners who update their sites regularly will be rewarded with a higher search engine ranking. Let’s look at how freelance writers can put this new update to use in their business.

      Visit Article


  9. Jaron Franklin Fort says:
    December 10, 2011 at 2:01 am

    Most programmers have never touched design. If you have always wanted to beautiful graphics in your Flash projects but never knew how to use Adobe Photoshop or Illustrator, this tutorial is for you. Nice graphics can be created entirely with code. Drawing graphics for components with code even has a few advantages.

    Prerequisites

    This tutorial requires that you know how to perform basic tweens using Greensock’s TweenLite or TweenMax. You can download the latest version of TweenLite from the Greensock website. I will be using Flash CS5 Professional to complete this project. You may use any Flash IDE you’d like (such as FlashDevelop or FDT). It would also help to have a fair understanding of inheritance.

    A Brief Introduction

    Before we get started, let’s take a look at what we’ll be learning and why it’s important. When designing Flash applications there are many ways to generate graphics. You can use an external tool such as Adobe Illustrator or draw complex graphics with Adobe Photoshop. You can even use 3D utilities such as Cinema 4D to create eye-popping 3D bitmaps to import into Flash. These techniques are great for creating a well designed static application – static meaning not very dynamic, or in most cases, not dynamic at all.

    If you use one of the above methods to generate graphics for Flash, you may find it a little difficult to resize the graphics without some loss of quality or, even worse, distortion. On the sunny side, you can import a vector file that was generated with Adobe Illustrator into your Flash application and scale the image infinitely without distorting the image – but when you want to change the overall ratio of the image, you will notice that your image becomes a little deformed.

    What we are going to do today is learn how efficient it can be to draw our application’s graphics with code. We are going to create a beautiful animated button that is completely generated with ActionScript.

    Step 1: Pros and Cons

    Before we dig in, I’d like to discuss the importance of planning for your application and answering simple questions to decide whether to draw the graphics with code or by hand (e.g. with Adobe Photoshop). To help us answer the questions below, let’s first examine the pros and cons to drawing with code.

    The Pros

    • Portability: Graphics that are written in code are easy to import into other projects since they exist as AS files. No need to copy and paste an image into a new Flash project or import the image into the library. Just import the appropriate classes.
    • Simplicity: Graphics drawn with code are done using vectors so they have a delicate and simplistic feel that is both nice to look at and light on the CPU.
    • Consistency: When you’d like to resize your graphics, they will not distort (unless this is the effect you are going for) and they will maintain quality as the are scaled. Bitmap images, for example, become pixelated as they are made larger or zoomed into. Vector images don’t lose any quality or become pixelated. You can zoom into a vector image infinately and it will never lose quality. You can also be sure that your graphics still look amazing on screens with higher resolutions. As technology advances and new screen resolutions become available, your graphics are more likely to still be able to deliver a nice quality, as opposed to bitmap images that may not look so good.
    • Dynamics: Along with being able to resize and scale your graphics, you can also re-color segments of an image or component with very few lines of code. Changing properties of a graphic has never been so easy. What’s that you say? You no longer want the frame of your textfield to have rounded edges? No problem here. I’ll just change one line of code… and we’re good to go!
    • Precision: Although many graphics applications have features that simplify the positioning of graphical segments, you’ll find it easier to make modifications and position the contents of a graphic with code. You can easily center one segment inside another as the parent segment changes size or write an algorithm for handling how a segment will be displayed as it is resized. Hint, hint.

    The Cons

    • Detail: Vector graphics drawn with code can be very detailed, but too much detail can have a dramatic effect on the performance of our applications. Although it may be possible, you won’t find me attempting to draw a detailed Spongebob Squarepants with code. Something like that should be done using Adobe Illustrator. Also vectors may not be able to be as detailed as a complex graphic drawn in Adobe Photoshop. Vectors tend to contain a smaller file size than your typical bitmap image. Vectors are connected points and bitmaps are represented pixel by pixel. But if you converted a bitmap into a vector image, the new vector’s file size would turn out to be a lot larger than the original bitmap image. This said, you won’t be able to paint an intricate portrait with code. Use Adobe Photoshop instead.
    • Limitations: There may be times where you’d like to use your graphics in different media. Sorry to say it but if you won’t be able to drop your dynamic graphics into that Java game you’ve been working on or that Objective-C application you just started. There are ways to render images using Flash but you will definately lose any dynamic capabilities provided by code.
    • Difficulty: Not to say that you will find it ridiculously difficult to draw graphics with code but depending on what you are drawing, you will most likely find the entire process a bit more complicated than using a software that is intended for this purpose. Don’t expect drawing with code to be an easy task. It really all depends on the expected outcome.

    You should now find the following questions pretty easy to answer. There are three questions you need to ask yourself before you start your project:

    1. Does your application require graphics to be static or dynamic?

      1. Static
      2. Dynamic
    2. Do the graphics or components in your application need to be exclusive to Flash or be consistent across multiple platforms?

      1. Flash Platform only
      2. Multiple Platforms
    3. Is the graphic design of your application more detailed or quite simple?

      1. Relatively Simple (Basic Geometric Shapes)
      2. Moderate (Creative Designs with Simple Shapes)
      3. Intricate (Overly Complex Masterpieces)

    Now examine your test results. If your test results closely resemble the results below, than the techniques we are getting ready to learn are for you?

    1. #2
    2. #1
    3. #1 or #2

    If your results do not look like the results above, you may want to consider other methods. But for the rest of us, let’s proceed.

    Step 2: Brainstorming

    So here’s the scenario. A client has just asked us to create an animated button for their Flash site and AIR app. The button must be consistent with the science fiction theme of the client’s website. The button’s height can be a fixed size but the button must be able to accomodate for different widths. The button must have a toggle state that has a blatant difference between it’s active and inactive states. Finally the button must have an API that’s easy to work with.

    Now that we know that we’ve got this themed component to create, we need to think about how we are going to go about creating it. Well, we know that we’re going to be drawing a lot of graphics with code so that the component will be easily and efficiently editable. Why not start off with a base class that will add high level functionality on top Flash’s drawing API?

    We don’t want to draw graphics over and over again by writing the same lines of code so we’ll have a class with particular properties and methods specifically designed for reusing the code for us. We’ll extend this class to create the main shapes that we’ll need for our button.

    Step 3: The Editable Shape Class

    Now it’s time to get to it! Create a new class called EditableShape and add the following classes to the classpath.

    
    
    import flash.display.Graphics;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.display.BitmapData;
    import flash.utils.getDefinitionByName;
    import flash.utils.getQualifiedClassName;
    

    Now create the class declaration. The class should extend the flash.display.Sprite class.

    
    
    public class EditableShape extends Sprite {
    

    Create the following variables(properties) before the class constructor.

    
    
    private var _fillGradientType:String;
    private var _fillSpreadMethod:String;
    private var _fillColors:Array;
    private var _fillAlphas:Array;
    private var _fillRatios:Array;
    private var _fillGradientWidth:Number;
    private var _fillGradientHeight:Number;
    private var _fillGradientRotation:Number;
    private var _fillTx:Number;
    private var _fillTy:Number;
    private var _lineGradientType:String;
    private var _lineSpreadMethod:String;
    private var _lineThickness:Number;
    private var _lineColors:Array;
    private var _lineAlphas:Array;
    private var _lineRatios:Array;
    private var _lineGradientWidth:Number;
    private var _lineGradientHeight:Number;
    private var _lineGradientRotation:Number;
    private var _lineTx:Number;
    private var _lineTy:Number;
    
    private var _width:Number;
    private var _height:Number;
    private var _matchGradientSize:Boolean;
    private var _bitmapData:BitmapData;
    private var _useBitmapFill:Boolean;
    private var _pixelHinting:Boolean;
    
    protected var fillGradientBox:Matrix;
    protected var lineGradientBox:Matrix;
    

    Within the class constructor add the following code and I’ll explain what we just did.

    
    
    super();
    _width = 100;
    _height = 100;
    _matchGradientSize = true;
    _fillGradientType = "linear";
    _fillSpreadMethod = "pad";
    _fillColors = [ 0xFFFFFF, 0x000000 ];
    _fillAlphas = [ 1, 1 ];
    _fillRatios = [ 1, 255 ];
    _fillGradientWidth = _width;
    _fillGradientHeight = _height;
    _fillGradientRotation = 0;
    _fillTx = 0;
    _fillTy = 0;
    _lineGradientType = "linear";
    _lineSpreadMethod = "pad";
    _lineThickness = .1;
    _lineColors = [ 0xFFFFFF, 0x000000 ];
    _lineAlphas = [ 1, 1 ];
    _lineRatios = [ 1, 255 ];
    _lineGradientWidth = _width;
    _lineGradientHeight = _height;
    _lineGradientRotation = 0;
    _lineTx = 0;
    _lineTy = 0;
    _useBitmapFill = false;
    _pixelHinting = true;
    fillGradientBox = new Matrix();
    lineGradientBox = new Matrix();
    init();
    

    The primary function of the constructor is to instantiate all of the properties that we have defined. We also gave each property a default value. You will be able to see what the result of these values are later. Each property that begins with an underscore will be given read/write access to outside code. The reasons these properties are not public properites is because we want to respond to the change in value of each particular property. We shall do this within the setter methods that we’ll create later.

    Each property is based on particular value that must be passed into any of the graphics object methods. One example is the _fillGradientColors property. It is an array of uints that will be passed into the graphics.beginGradientFill method. Another example is the _pixelHinting property. It will be passed into the graphics.lineStyle method’s pixelHinting parameter.

    The last line of the constuctor calls the init method. The init method is very simple. It calls the update method.

    Step 4: The Update Method

    The update method is probably the most important method within the EditableShape class. The main objective of this method is to clear any existing graphics and redraw them based upon the latest data. We will call this method everytime a property has changed so the changes can be seen immediately by the user if necassary. Create the update method.

    
    
    protected function update():void {
    
    	if ( _matchGradientSize ) {
    
    		_lineGradientWidth = _width;
    		_lineGradientHeight = _height;
    		_fillGradientWidth = _width;
    		_fillGradientHeight = _height;
    	}
    
    	lineGradientBox.createGradientBox( lineGradientWidth, lineGradientHeight, toRadians( lineGradientRotation ), lineTx, lineTy );
    	fillGradientBox.createGradientBox( fillGradientWidth, fillGradientHeight, toRadians( fillGradientRotation ), fillTx, fillTy );
    	super.graphics.clear();
    	super.graphics.lineStyle( lineThickness, 0, 0, pixelHinting );
    	super.graphics.lineGradientStyle( lineGradientType, lineColors, lineAlphas, lineRatios, lineGradientBox, lineSpreadMethod );
    	if ( !_bitmapData || !_useBitmapFill ) super.graphics.beginGradientFill( fillGradientType, fillColors, fillAlphas, fillRatios, fillGradientBox, fillSpreadMethod )
    	else super.graphics.beginBitmapFill( _bitmapData );
    
    	draw();
    }
    

    The Matrix objects we created in the constructor are used to manipulate gradients. We needed two of them. One for the fill gradient and the other for the line gradient.

    We will be overriding the get graphics method so that we can forbid access to this property to outside code. We don’t want any outside code tampering with our graphics at all. Because we are going to override the get graphics method, we will need to access the method from the subclass. This is accomplished through the super object. We will also create a protected method called getGraphics later on. This method is needed to give subclasses access to the graphics object without granting access to the object to outside code.

    In conclusion, the update method re-initializes the graphics and it does this based on the current values of the properties within the EditableShape instance. The last line of code calls the draw method which is an abstract method in the EditableShape class. The method should be overriden by a subclass and is intended for drawing a particular shape using the graphics object within its implementation.

    Step 5: Clones and Copies

    Create the draw method.

    
    
    protected function draw():void {
    
    	// Abstract
    }
    

    Again the draw method is just a simple abstract method that we can ignore for now.

    We will need to copy the properties of one shape onto another. There may also be times when you’d like a complete clone of a particular shape. We’ll create two methods to accomplish this for us. Doing so will save us a lot of time in the long run. Instead of always re-writing code we’ll just call the appropriate method which copies or clones a shape. Create the copy and clone methods.

    
    
    public function copy( shape:EditableShape ):void {
    
    	_width = shape.width;
    	_height = shape.height;
    	_matchGradientSize = shape.matchGradientSize;
    	_fillGradientType = shape.fillGradientType;
    	_fillSpreadMethod = shape.fillSpreadMethod;
    	_fillColors = shape.fillColors;
    	_fillAlphas = shape.fillAlphas;
    	_fillRatios = shape.fillRatios;
    	_fillGradientWidth = shape.fillGradientWidth;
    	_fillGradientHeight = shape.fillGradientHeight;
    	_fillGradientRotation = shape.fillGradientRotation;
    	_fillTx = shape.fillTx;
    	_fillTy = shape.fillTy;
    	_lineGradientType = shape.lineGradientType;
    	_lineSpreadMethod = shape.lineSpreadMethod;
    	_lineThickness = shape.lineThickness;
    	_lineColors = shape.lineColors;
    	_lineAlphas = shape.lineAlphas;
    	_lineRatios = shape.lineRatios;
    	_lineGradientWidth = shape.lineGradientWidth;
    	_lineGradientHeight = shape.lineGradientHeight;
    	_lineGradientRotation = shape.lineGradientRotation;
    	_lineTx = shape.lineTx;
    	_lineTy = shape.lineTy;
    	_useBitmapFill = shape.useBitmapFill;
    	if ( _bitmapData ) _bitmapData = shape.bitmapData.clone();
    	if ( filters ) filters = shape.filters;
    	alpha = shape.alpha;
    	update();
    }
    
    public function clone():EditableShape {
    
    	var c:Class = Class( getDefinitionByName( getQualifiedClassName( this ) ) );
    	var shape:EditableShape = new c();
    	shape.width = _width;
    	shape.height = _height;
    	shape.matchGradientSize = _matchGradientSize;
    	shape.fillGradientType = _fillGradientType;
    	shape.fillSpreadMethod = _fillSpreadMethod;
    	shape.fillColors = _fillColors;
    	shape.fillAlphas = _fillAlphas;
    	shape.fillRatios = _fillRatios;
    	shape.fillGradientWidth = _fillGradientWidth;
    	shape.fillGradientHeight = _fillGradientHeight;
    	shape.fillGradientRotation = _fillGradientRotation;
    	shape.fillTx = _fillTx;
    	shape.fillTy = _fillTy;
    	shape.lineGradientType = _lineGradientType;
    	shape.lineSpreadMethod = _lineSpreadMethod;
    	shape.lineThickness = _lineThickness;
    	shape.lineColors = _lineColors;
    	shape.lineAlphas = _lineAlphas;
    	shape.lineRatios = _lineRatios;
    	shape.lineGradientWidth = _lineGradientWidth;
    	shape.lineGradientHeight = _lineGradientHeight;
    	shape.lineGradientRotation = _lineGradientRotation;
    	shape.lineTx = _lineTx;
    	shape.lineTy = _lineTy;
    	shape.useBitmapFill = _useBitmapFill;
    	if ( _bitmapData ) shape.bitmapData = _bitmapData.clone();
    	shape.filters = filters;
    	shape.alpha = alpha;
    	return shape;
    }
    

    The copy method takes the shape parameter and sets all of the properties equal to that of the current EditableShape.

    We will not be using the clone method in this tutorial but I just threw it in as an extra bonus. The method returns a cloned copy of the current EditableShape class.

    Step 6: Finishing Up the EditableShape

    The last thing we need to do is grant read/write access to all of the shape’s main properties. Write the following getter and setter methods within the EditableShape class.

    
    
    		public override function set width(value:Number):void {
    
    			_width = value;
    			update();
    		}
    
    		public override function get width():Number {
    
    			return _width;
    		}
    
    		public override function set height(value:Number):void {
    
    			_height = value;
    			update();
    		}
    
    		public override function get height():Number {
    
    			return _height;
    		}
    
    		public function set fillGradientType( value:String ):void {
    
    			switch ( value.toLowerCase() ) {
    
    				case "linear" :
    				case "radial" :
    					_fillGradientType = value.toLowerCase();
    					update();
    					break;
    				default :
    					//Do nothing
    			}
    		}
    
    		public function get fillGradientType():String {
    
    			return _fillGradientType;
    		}
    
    		public function set fillSpreadMethod(value:String):void {
    
    			switch ( value.toLowerCase() ) {
    
    				case "pad" :
    				case "reflect" :
    				case "repeat" :
    					_fillSpreadMethod = value.toLowerCase();
    					update();
    				default :
    					//Do nothing
    			}
    		}
    
    		public function get fillSpreadMethod():String {
    
    			return _fillSpreadMethod;
    		}
    
    		public function set fillColors(array:Array):void {
    
    			var a:Array = [];
    
    			for each( var color:uint in array ) {
    
    				if ( color is uint ) {
    
    					a.push( color );
    				}
    			}
    
    			_fillColors = a;
    			update();
    		}
    
    		public function get fillColors():Array {
    
    			return _fillColors;
    		}
    
    		public function set fillAlphas( array:Array ):void {
    
    			var a:Array = [];
    
    			for each( var nAlpha:Number in array ) {
    
    				if ( nAlpha is Number)  {
    
    					a.push( nAlpha );
    				}
    			}
    
    			_fillAlphas = a;
    			update();
    		}
    
    		public function get fillAlphas():Array {
    
    			return _fillAlphas;
    		}
    
    		public function set fillRatios(array:Array):void {
    
    			var a:Array = [];
    
    			for each(var ratio:Number in array) {
    
    				if (ratio is int) {
    
    					a.push(ratio);
    				}
    			}
    
    			_fillRatios = a;
    			update();
    		}
    
    		public function get fillRatios():Array {
    
    			return _fillRatios;
    		}
    
    		public function set fillGradientWidth(value:Number):void {
    
    			_fillGradientWidth = value;
    			update();
    		}
    
    		public function get fillGradientWidth():Number {
    
    			return _fillGradientWidth;
    		}
    
    		public function set fillGradientHeight(value:Number):void {
    
    			_fillGradientHeight = value;
    			update();
    		}
    
    		public function get fillGradientHeight():Number {
    
    			return _fillGradientHeight;
    		}
    
    		public function set fillGradientRotation(degrees:Number):void {
    
    			_fillGradientRotation = degrees;
    			update();
    		}
    
    		public function get fillGradientRotation():Number {
    
    			return _fillGradientRotation;
    		}
    
    		public function set fillTx(value:Number):void {
    
    			_fillTx = value;
    			update();
    		}
    
    		public function get fillTx():Number {
    
    			return _fillTx;
    		}
    
    		public function set fillTy(value:Number):void {
    
    			_fillTy = value;
    			update();
    		}
    
    		public function get fillTy():Number {
    
    			return _fillTy;
    		}
    
    		public function set lineGradientType(value:String):void {
    
    			switch (value.toLowerCase()) {
    
    				case "linear" :
    				case "radial" :
    					_lineGradientType = value.toLowerCase();
    					update();
    					break;
    				default :
    					//Do nothing
    			}
    		}
    
    		public function get lineGradientType():String {
    
    			return _lineGradientType;
    		}
    
    		public function set lineSpreadMethod(value:String):void {
    
    			switch (value.toLowerCase()) {
    
    				case "pad" :
    				case "reflect" :
    				case "repeat" :
    					_lineSpreadMethod = value.toLowerCase();
    					update();
    				default :
    					//Do nothing
    			}
    		}
    
    		public function get lineSpreadMethod():String {
    
    			return _lineSpreadMethod;
    		}
    
    		public function set lineThickness(value:Number):void {
    
    			_lineThickness = value;
    			update();
    		}
    
    		public function get lineThickness():Number {
    
    			return _lineThickness;
    		}
    
    		public function set lineColors(array:Array):void {
    
    			var a:Array = [];
    
    			for each(var color:uint in array) {
    
    				if (color is uint) {
    
    					a.push(color);
    				}
    			}
    
    			_lineColors = array;
    			update();
    		}
    
    		public function get lineColors():Array {
    
    			return _lineColors;
    		}
    
    		public function set lineAlphas(array:Array):void {
    
    			var a:Array = [];
    
    			for each(var nAlpha:Number in array) {
    
    				if (nAlpha is Number) {
    
    					a.push(nAlpha);
    				}
    			}
    
    			_lineAlphas = a;
    			update();
    		}
    
    		public function get lineAlphas():Array {
    
    			return _lineAlphas;
    		}
    
    		public function set lineRatios(array:Array):void {
    
    			var a:Array = [];
    
    			for each(var ratio:Number in array) {
    
    				if (ratio is int) {
    
    					a.push(ratio);
    				}
    			}
    
    			_lineRatios = a;
    			update();
    		}
    
    		public function get lineRatios():Array {
    
    			return _lineRatios;
    		}
    
    		public function set lineGradientWidth(value:Number):void {
    
    			_lineGradientWidth = value;
    			update();
    		}
    
    		public function get lineGradientWidth():Number {
    
    			return _lineGradientWidth;
    		}
    
    		public function set lineGradientHeight(value:Number):void {
    
    			_lineGradientHeight = value;
    			update();
    		}
    
    		public function get lineGradientHeight():Number {
    
    			return _lineGradientHeight;
    		}
    
    		public function set lineGradientRotation(degrees:Number):void {
    
    			_lineGradientRotation = degrees;
    			update();
    		}
    
    		public function get lineGradientRotation():Number {
    
    			return _lineGradientRotation;
    		}
    
    		public function set lineTx(value:Number):void {
    
    			_lineTx = value;
    			update();
    		}
    
    		public function get lineTx():Number {
    
    			return _lineTx;
    		}
    
    		public function set lineTy(value:Number):void {
    
    			_lineTy = value;
    			update();
    		}
    
    		public function get lineTy():Number {
    
    			return _lineTy;
    		}
    
    		public function set matchGradientSize(value:Boolean):void {
    
    			_matchGradientSize = value;
    			update();
    		}
    
    		public function get matchGradientSize():Boolean {
    
    			return _matchGradientSize;
    		}
    
    		public function set bitmapData( value:BitmapData ):void {
    
    			_bitmapData = value;
    			update();
    		}
    
    		public function get bitmapData():BitmapData {
    
    			return _bitmapData;
    		}
    
    		public function set useBitmapFill( value:Boolean ):void {
    
    			_useBitmapFill = value;
    			update();
    		}
    
    		public function get useBitmapFill():Boolean {
    
    			return _useBitmapFill;
    		}
    
    		public function set firstFillColor( value:uint ):void {
    
    			_fillColors[ 0 ] = value;
    			update();
    		}
    
    		public function get firstFillColor():uint {
    
    			if ( _fillColors.length > 0 ) {
    
    				return _fillColors[ 0 ];
    			}
    			else {
    
    				return 0;
    			}
    		}
    
    		public function set pixelHinting( value:Boolean ):void {
    
    			_pixelHinting = value;
    			update();
    		}
    
    		public function get pixelHinting():Boolean {
    
    			return _pixelHinting;
    		}
    
    		public override function get graphics():Graphics {
    
    			return null;
    		}
    
    		protected function getGraphics():Graphics {
    
    			return super.graphics;
    		}
    

    All of the getter methods just return the corresponding properties value. But for the setter methods we correct or filter out any unwanted input. We also call the update method so that there is an immediate reaction to the new value or values.

    Step 7: Drawing Rectangles

    The majority of our button will consist of rectangle shapes. Unless we want to bore our client’s users with a bunch of lame blocky shapes, we will want to be able to round the edges of our rectangles. The EditableShape class is meant to be extended, meaning that it should have subclasses that finalize the primary function of the class. The EditableShape class takes care of all of the hard work for us. All we have to do now is draw the shape within a subclass. Create a new class called RectangleShape which extends the EditableShape class. The class declaration should look as follows.

    
    
    public class RectangleShape extends EditableShape {
    

    Add the following private properties to the class directly after the class declaration.

    
    
    private var _ellipseWidth:Number;
    private var _ellipseHeight:Number;
    

    I mentioned before that we will be rounding the edges to our rectangles. As you have probably guessed already, we will be granting read/write access to these properties just as we did with all of the other inherited properties. This will allow us to react to any change the ellipseWidth and ellipseHeight properties immediately after they have been altered.

    Reminder: This is accomplished by calling the update method.

    Create the class constructor. Give the _ellipseWidth and _ellipseHeight properties a default value of 0. We don’t want the edges to be rounded by default.

    
    
    public function RectangleShape() {
    
    	_ellipseWidth = 0;
    	_ellipseHeight = 0;
        super();
    }
    

    You should remember the draw method from the EditableShape class was an abstract method. That is a method that has an empty implementation. We are going to override this method to give it the proper functionality. The methods name is self explanatory. The method will do the actual drawing of the shape.

    Important: We call the base class’s constructor, super(), after we have assigned a value to the _ellipseWidth and _ellipseHeight properties. Remember the the constructor initializes the shape by calling the init method which then calls the update method which finally calls the draw method. You will see in a minute that the draw method requires these properties. Forgeting to call the constructor last will result in an argument error thrown by the drawRoundRect method of the graphics object.

    
    
    protected override function draw():void {
    
    	getGraphics().drawRoundRect( 0, 0, width, height, _ellipseWidth, _ellipseHeight );
    }
    

    I have to apologize to all of you who were expecting ten or more lines of code here in the draw method. That’s not the case here. Remember that the base class(EditableShape) does most of the work for us. It handles colors, gradients, alphas, line properties and so on. All we needed to do is draw the shape and that’s what we’ve done. The graphics object can no longer be accessed by outside code since the property has been overriden so we had to access it through the protected method, getGraphics. Finally we call the drawRoundRect method on the graphics object and we pass in the appropriate parameters.

    Step 8: Overriding the Copy and Clone Methods

    There are two more methods we need to override before we can conclude this class. The first method is the copy method. This is the method from the EditableShape class that takes an EditableShape as a parameter and causes the properties of the parent shape onto the parameter shape. We need add some functionality to this method. We will be overriding this method but that doesn’t mean that we have to forget everything that the base class does with this method. We’ll use the super object to call the method from the base class so that it inherits its original functionality while adding new functionality to it.

    
    
    public override function copy( shape:EditableShape ):void {
    
    	super.copy( shape );
    
    	if ( shape is RectangleShape ) {
    
    		var rect:RectangleShape = shape as RectangleShape;
    		ellipseWidth = rect.ellipseWidth;
    		ellipseHeight = rect.ellipseHeight;
    	}
    }
    

    Can you tell what just happened? If the parameter, shape, is a RectangleShape we also copy the ellipseWidth and ellipseHeight properties. If you have a collection of RectangleShapes, that you are using to draw a graphic with, and you’d like them all to have the same ellipseWidth and ellipseHeight properties, this will keep you from writing too many extra lines of code.

    The second method we need to override is the clone method.

    
    
    public override function clone():EditableShape {
    
    	var shape:RectangleShape = super.clone() as RectangleShape;
    	shape.ellipseWidth = _ellipseWidth;
    	shape.ellipseHeight = _ellipseHeight;
    	return shape;
    }
    

    The clone method also inherits the implementation of the base class. But with this implementation we have added the ellipseWidth and ellipseHeight properties.

    Step 9: More Access

    Write the following getter and setter methods:

    
    
    public function set ellipseWidth( value:Number ):void {
    
    	if ( value < 0 ) value = 0;
    	_ellipseWidth = value;
    	update();
    }
    
    public function get ellipseWidth():Number {
    
    	return _ellipseWidth;
    }
    
    public function set ellipseHeight( value:Number ):void {
    
    	if ( value < 0 ) value = 0;
    	_ellipseHeight = value;
    	update();
    }
    
    public function get ellipseHeight():Number {
    
    	return _ellipseHeight;
    }
    

    We have not only granted the read/write access that is needed by outside code, but we have also made sure that the ellipseWidth and ellipseHeight are never below zero. There is also an immediate reaction to these properties being set or changed.

    Note: If you do not want to correct any values for the ellipseWidth or ellispeHeight properties, you do not have to. There may be a time when you’d want the ellipseWidth or ellipseHeight to be less than zero.

    Now that we have our first shape complete. Let’s take a quick look at what our shape looks like when we first create it. You will need to create a document class and create a new instance of the RectangleShape object within it. Add the new RectangleShape to the stage. Here’s my code:

    
    
    stage.addChild( new RectangleShape() );
    

    Let’s look at the result.

    This is the what our shape looks like by default. Feel free to play around with it a bit so that you get a good feel for it. Try changing the colors or modifying the size.

    Step 9: Drawing Circles

    We are going to create a sort of bubbling effect for the over state of our button. This means that we will need bubbles. Create the EclipseShape class. Make sure that it extends the EditableShape class.

    
    
    package {
    
    	public class EllipseShape extends EditableShape {
    
    		public function EllipseShape() {
    
    			super();
    		}
    
    		protected override function draw():void {
    
    			getGraphics().drawEllipse( 0, 0, width, height );
    		}
    	}
    }
    

    Once again the power of inheritance has allowed us to recycle old code instead of writing the same code over and over again. This class only contains inherited properties and methods. We had to override the draw method in order to create the actual eclipse shape though. The drawEclipse method uses the inherited width and height properties to draw our shape. And once again we access the graphics object using the protected getGraphics method.

    We now have all of the shapes we need to draw our button.

    Step 10: Starting the Button

    Create a new class that extends flash.display.Sprite. You can call the class whatever you’d like. I’m going to use the name MyButton. Import the following classes.

    
    
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.filters.BlurFilter;
    import flash.filters.GlowFilter;
    import flash.events.MouseEvent;
    import flash.filters.DropShadowFilter;
    import flash.system.System;
    import flash.filters.BevelFilter;
    import com.greensock.TweenMax;
    
    public class MyButton extends Sprite {
    

    Define the following properties.

    
    
    private var _width:Number;
    private var _active:Boolean;
    private var base:RectangleShape;
    private var toggleBase:RectangleShape;
    private var txt:TextField;
    private var effectTxt:TextField;
    private var toggleTxt:TextField;
    private var toggleGlass:RectangleShape;
    private var toggleGlassAlpha:Number;
    private var ref:RectangleShape;
    private var light:RectangleShape;
    private var lightAlpha:Number;
    private var glow:RectangleShape;
    private var effectMask:RectangleShape;
    private var txtMask:RectangleShape;
    private var effectTxtMask:RectangleShape;
    private var toggleTxtMask:RectangleShape;
    private var effectContainer:Sprite;
    private var circles:Array;
    private var tweens:Array;
    private var circleBlur:BlurFilter;
    private var _toggle:Boolean;
    

    Just like before, any property that starts with an underscore is either expected to cause an immediate reaction when set or the property will be read-only.

    The _width property will be used to override the width property of the base class and we redraw the shape everytime the width property is set.

    The active property is going to be used to swap the toggle states of the button later.

    You will notice several properties that are RectangleShapes, several properties that are TextFields, and a Sprite. We will see the role each of these properties play later.

    We’ll be storing all of our bubbles in the circles Array. To improve performance we will need to pause various tweens. In order to do this we will need to store these tweens in an array so that they can be accessed whenever we need them.

    Last we have the circleBlur property which is a BlurFilter that is to be applied to each bubble, and we have the _toggle property which affects the behavior of the button.

    Create the following public constants.

    
    
    public static const BUTTON_HEIGHT:Number = 40;
    public static const NUM_OF_CIRCLES:uint = 12;
    

    The height of our button will not change so it’s appropriate to store the value of the button’s height in a class constant. The size of the button’s ellipse is relative to the button’s height. If the button becomes too large or too small, our button may lose the Pill Button look that we are going for. Also the number of bubbles is predetermined so we store this value in a class constant as well.

    Step 11: The Base

    When ever I am drawing graphics for a component like a text field or a button, I always, always, always… start with a base shape. This is a shape that acts as the foundation of the shape. It is the backbone of the component. How the graphic is structured is entirely dependent on how I construct the base.

    You will notice a property that we have defined called toggleBase. I am not talking about this property. I am talking about the base property itself. This shape will define the outline of the button. Let’s create this property and initialize its values now. Add the following code to the constructor of the class that you have defined as your button.

    
    
    public function MyButton() {
    
    	super();
    	buttonMode = true;
    	mouseChildren = false;
    	_width = 100;
    
    	base = new RectangleShape();
    	base.height = BUTTON_HEIGHT;
    	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
    	base.fillGradientRotation = 90;
    	base.fillColors = [ 0xAAAAAA, 0x444444 ];
    	base.lineColors = [ 0x222222 ];
    	base.lineAlphas = [ .5 ];
    	base.lineRatios = [ 1 ];
    
        addChild( base );
    }
    

    The default fillGradientRotation is 0. This value is in degrees but is converted into radians when passed into the gradient box(Matrix). Along with initializing the button’s size, we have to set the rotation of the gradient. In this case we want this value to be 90 degrees. We also set the fillColors (as an Array), and the lineColors.

    It is important to remember that the default value for these properties is an Array that has a length of two. All of the Array properties(lineColor,lineAlpha, and lineRatios) must be the same length. If they aren’t, the graphics will not draw. This is why we set the lineAlphas and lineRatios properties.

    If you test the Flash movie, you should get this.

    This is the overrall shape we are going for, “The Gel Pill”. Let’s make it shine a little bit.

    Step 12: The Reflection

    We’ve got the main structure of the button down already but now we need to add the small thing that I love to preach about. We need lots and lots of depth. We can start by adding the reflection. When light hits a glossy surface, it reflects off of the surface. Instantiate and initialize the ref (short for reflection) property.

    
    
    super();
    buttonMode = true;
    mouseChildren = false;
    _width = 100;
    
    base = new RectangleShape();
    base.height = BUTTON_HEIGHT;
    base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
    base.fillGradientRotation = 90;
    base.fillColors = [ 0xAAAAAA, 0x444444 ];
    base.lineColors = [ 0x222222 ];
    base.lineAlphas = [ .5 ];
    base.lineRatios = [ 1 ];
    
    ref = new RectangleShape();
    ref.fillGradientRotation = 90;
    ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
    ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
    ref.fillAlphas = [ 1, 0 ];
    ref.lineColors = [ 0 ];
    ref.lineAlphas = [ 0 ];
    ref.lineRatios = [ 0 ];
    ref.alpha = .5;
    ref.x = ref.ellipseHeight / 2;
    ref.width = _width - ref.height;
    
    addChild( base );
    addChild( ref );
    

    We have turned the alpha property down a little bit so the the reflection isn’t so intense but we have basically followed the same steps to draw the ref shape as we did with the base shape. And of course we have sized and positioned the reflection relative to the size of the button’s height. Let’s see what we have now.

    Not too bad. Still needs a lot more depth though. We’ll add some more later.

    Step 13: The Inner Light

    Sometimes when you are creating art, you notice that it’s those tiny little details that make the biggest difference in the appearance of your work. The light property will add the tiny detail into our button that makes all of the difference. This property will also be used a little differently in our button’s over and out states, but for now it will make our button appear to have a semi-transparent surface.

    Add the following code to your button’s constructor method.

    
    
    light = new RectangleShape();
    light.copy( ref );
    light.x = ref.x;
    light.y = BUTTON_HEIGHT - light.height;
    light.width = _width - light.height;
    light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
    light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
    light.alpha = lightAlpha = .3;
    
    addChild( light );
    

    The constructor should now look like this:

    
    
    public function MyButton() {
    
    	super();
    	buttonMode = true;
    	mouseChildren = false;
    	_width = 100;
    
    	base = new RectangleShape();
    	base.height = BUTTON_HEIGHT;
    	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
    	base.fillGradientRotation = 90;
    	base.fillColors = [ 0xAAAAAA, 0x444444 ];
    	base.lineColors = [ 0x222222 ];
    	base.lineAlphas = [ .5 ];
    	base.lineRatios = [ 1 ];
    
    	ref = new RectangleShape();
    	ref.fillGradientRotation = 90;
    	ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
    	ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
    	ref.fillAlphas = [ 1, 0 ];
    	ref.lineColors = [ 0 ];
    	ref.lineAlphas = [ 0 ];
    	ref.lineRatios = [ 0 ];
    	ref.alpha = .5;
    	ref.x = ref.ellipseHeight / 2;
    	ref.width = _width - ref.height;
    
    	light = new RectangleShape();
    	light.copy( ref );
    	light.x = ref.x;
    	light.y = BUTTON_HEIGHT - light.height;
    	light.width = _width - light.height;
    	light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
    	light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
    	light.alpha = lightAlpha = .3;
    
    	addChild( base );
    	addChild( light );
    	addChild( ref );
    }
    

    We have added a GlowFilter and a BlurFilter to this object so that we can achieve a specific look. We don’t want the shape to look like a shape at all but empty space within the button. Notice that we have used the copy method to mimic the properties of the ref object. There’s no need to write the same lines of code for the light object. Just mimic the ref property and make just a few modifications and you have yourself a new shape.

    See how we are beginning to see more depth as our shape is being constructed? The pill doesn’t look fully opaque and it isn’t very transparent either. We want an “Out of This World” kind of look so just in between is perfect.

    Step 14: Simple Text

    Now that we have a good foundation down on the table, it’s appropriate to begin adding the first TextField to the button. Initialize the txt property. And create a mask that is the same size and ellipse as the base so that the text doesn’t appear outside of the button.

    
    
    public function TutButton() {
    
    	super();
    	buttonMode = true;
    	mouseChildren = false;
    	_width = 100;
    
    	base = new RectangleShape();
    	base.height = BUTTON_HEIGHT;
    	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
    	base.fillGradientRotation = 90;
    	base.fillColors = [ 0xAAAAAA, 0x444444 ];
    	base.lineColors = [ 0x222222 ];
    	base.lineAlphas = [ .5 ];
    	base.lineRatios = [ 1 ];
    
    	ref = new RectangleShape();
    	ref.fillGradientRotation = 90;
    	ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
    	ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
    	ref.fillAlphas = [ 1, 0 ];
    	ref.lineColors = [ 0 ];
    	ref.lineAlphas = [ 0 ];
    	ref.lineRatios = [ 0 ];
    	ref.alpha = .5;
    	ref.x = ref.ellipseHeight / 2;
    	ref.width = _width - ref.height;
    
    	light = new RectangleShape();
    	light.copy( ref );
    	light.x = ref.x;
    	light.y = BUTTON_HEIGHT - light.height;
    	light.width = _width - light.height;
    	light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
    	light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
    	light.alpha = lightAlpha = .3;
    
    	txt = new TextField();
    	txt.selectable = false;
    	txt.type = "dynamic";
    	txt.wordWrap = false;
    	txt.multiline = false;
    	txt.autoSize = "left";
    	txt.defaultTextFormat = new TextFormat( null, 27 );
    	txt.textColor = 0x333333;
    	txt.text = "label";
    	txt.height = BUTTON_HEIGHT;
    
    	txtMask = new RectangleShape();
    	txtMask.copy( base );
    	txtMask.filters = [];
    	txt.mask = txtMask;
    
    	addChild( base );
    	addChild( light );
    	addChild( ref );
    	addChild( txt );
    	addChild( txtMask );
    }
    

    We have once again utilized the copy method by creating a copy of the base object. We could have very well have used the clone method also. The result would be the same. Also note that we have set the filters array of the txtMask object to a blank array. This is because when the copy method used the filters property is also inherited. We have just simply overriden this property. Let’s see where we’re at.

    We will position all of the TextFields later on. For now our txt will just have to hang out on the left side of our button.

    Step 15: Setting Up for the Over State

    Our button will illuminate and display a sort of science fiction like animation sequence with bubbles when the mouse hovers over the button. Of course the entire sequence will be accomplished 100% with code.

    But before we can do this we need to create the elements of the sequence. The first is the background object, or the glow property, of the over state. Let’s add the glow object now. Add the following code to the constructor method:

    
    
    glow = new RectangleShape();
    glow.copy( base );
    glow.fillColors = [ 0xFFFFFF ];
    glow.fillAlphas = [ 1 ];
    glow.fillRatios = [ 0 ];
    glow.lineColors = [ 0 ];
    glow.lineAlphas = [ 0 ];
    glow.lineRatios = [ 0 ];
    glow.filters = [ new GlowFilter( 0x00BCE9, 1, 10, 10, 2, 3, false, false ), new GlowFilter( 0x00BCE9, 1, 20, 20, 2, 3, true ) ];
    
    addChild( base );
    addChild( light );
    addChild( ref );
    addChild( txt );
    addChild( txtMask );
    addChild( glow );
    

    We will also need a container for the bubbles to be displayed in and a mask for that container so that the bubbles don’t float out of the button.

    
    
    public function MyButton() {
    
    	super();
    	buttonMode = true;
    	mouseChildren = false;
    	_width = 100;
    
    	base = new RectangleShape();
    	base.height = BUTTON_HEIGHT;
    	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
    	base.fillGradientRotation = 90;
    	base.fillColors = [ 0xAAAAAA, 0x444444 ];
    	base.lineColors = [ 0x222222 ];
    	base.lineAlphas = [ .5 ];
    	base.lineRatios = [ 1 ];
    
    	ref = new RectangleShape();
    	ref.fillGradientRotation = 90;
    	ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
    	ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
    	ref.fillAlphas = [ 1, 0 ];
    	ref.lineColors = [ 0 ];
    	ref.lineAlphas = [ 0 ];
    	ref.lineRatios = [ 0 ];
    	ref.alpha = .5;
    	ref.x = ref.ellipseHeight / 2;
    	ref.width = _width - ref.height;
    
    	light = new RectangleShape();
    	light.copy( ref );
    	light.x = ref.x;
    	light.y = BUTTON_HEIGHT - light.height;
    	light.width = _width - light.height;
    	light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
    	light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
    	light.alpha = lightAlpha = .3;
    
    	txt = new TextField();
    	txt.selectable = false;
    	txt.type = "dynamic";
    	txt.wordWrap = false;
    	txt.multiline = false;
    	txt.autoSize = "left";
    	txt.defaultTextFormat = new TextFormat( null, 27 );
    	txt.textColor = 0x333333;
    	txt.text = "label";
    	txt.height = BUTTON_HEIGHT;
    
    	txtMask = new RectangleShape();
    	txtMask.copy( base );
    	txtMask.filters = [];
    	txt.mask = txtMask;
    
    	glow = new RectangleShape();
    	glow.copy( base );
    	glow.fillColors = [ 0xFFFFFF ];
    	glow.fillAlphas = [ 1 ];
    	glow.fillRatios = [ 0 ];
    	glow.lineColors = [ 0 ];
    	glow.lineAlphas = [ 0 ];
    	glow.lineRatios = [ 0 ];
    	glow.filters = [ new GlowFilter( 0x00BCE9, 1, 10, 10, 2, 3, false, false ), new GlowFilter( 0x00BCE9, 1, 20, 20, 2, 3, true ) ];
    
    	effectContainer = new Sprite();
    	effectContainer.cacheAsBitmap = true;
    
    	effectMask = new RectangleShape();
    	effectMask.copy( base );
    	effectMask.filters = [];
    	effectContainer.mask = effectMask;
    
    	addChild( base );
    	addChild( light );
    	addChild( ref );
    	addChild( txt );
    	addChild( txtMask );
    	addChild( glow );
    	addChild( effectContainer );
    	addChild( effectMask );
    }
    

    Step 16: Bubbles

    Now we are going to blow a few bubbles. Add the following lines of code to the constructor method:

    
    
    circleBlur = new BlurFilter( 5, 5, 3 );
    circles = [];
    tweens = [];
    

    The circleBlur is a BlurFilter that will be applied to all bubbles. This will give each bubble the specific science like look that we’re going for. We also need to create the arrays that will store all of the bubbles and the tweens that will animate each bubble.

    We need a method that will generate all of the bubbles we need.

    
    
    private function createEffect():void {
    
    	for ( var i:int = 0; i < NUM_OF_CIRCLES; i++ ) {
    
    		var circ:EllipseShape = new EllipseShape();
    		resetCircle( circ );
    	}
    
    	stopEffect();
    }
    

    Use a loop to iterate a block of code that creates a new EllipseShape object, or in this case a bubble, and run the resetCircle method on the bubble. We haven’t created this method yet but it re-initializes the parameter bubble. In the loop, the method simply initializes each bubble since they haven’t been initialized to begin with. Finally the stopEffect method is called. This method pauses the bubble’s animation sequence. We’ll write this method in a bit.

    For now, create the following methods. (Also now is a good time to import com.greensock.TweenMax).

    
    
    private static function randomNumber( min:int = 0, max:int = 10 ):int {
    
    	return Math.round( Math.random() * ( max - min ) + min );
    }
    
    private function resetCircle( circle:EllipseShape ):void {
    
    	circle.width = circle.height = randomNumber( 10, 20 );
    	effectContainer.addChild( circle );
    	circle.cacheAsBitmap = true;
    	circle.x = randomNumber( 0, _width );
    	circle.y = BUTTON_HEIGHT;
    	circle.filters = [ circleBlur ];
    
    	if ( circles.indexOf( circle ) == -1 ) {
    
    		circles.push( circle );
    		circle.fillColors = [ 0x00BCE9 ];
    		circle.fillAlphas = [ 1 ];
    		circle.fillRatios = [ 1 ];
    		circle.lineAlphas = [ 0 ];
    		circle.lineRatios = [ 0 ];
    		circle.lineColors = [ 0 ];
    		circle.alpha = .6;
    	}
    
    	var tween:TweenMax = TweenMax.to( circle, randomNumber( 1, 6 ) * .5, { y:-BUTTON_HEIGHT, onComplete:doComplete } );
    	tweens.push( tween );
    
    	function doComplete():void {
    
    		resetCircle( circle );
    		removeTween( tween );
    	}
    }
    
    private function removeTween( tween:TweenMax ):void {
    
    	var a:Array = [];
    
    	for each( var t:TweenMax in tweens ) {
    
    		if ( t != tween ) a.push( t );
    	}
    
    	tweens = null;
    	System.gc();
    	tweens = a;
    }
    

    The randomNumber method returns a random number based on the parameters passed into the method. The first parameter specifies a the minimum value that can be generated and the second parameter specifies the maximum value that can be generated. We need this method to generate a random location and size for a bubble when we reset a bubble.

    This brings me to the resetCircle method. I said before that this method re-initializes the specified bubble. To be more specific, the method recycles a bubble and makes it appear like a brand new bubble that has just been created when in reality it is just another old bubble.

    The to method from the TweenMax class returns the tween that the bubble contains. We push this bubble into the tweens array. The bubble starts below the button and rises above the button. When the tween is finished it is no longer needed. The tween needs to be removed (using the removeTween method) and the bubble needs to be reset or recycled. The anonymous function doComplete does just that.

    Before we can see what our bubbles look like we need to create two methods that will control playback of the bubbles’ animation sequence. Besides if we added a call to the createEffect method in the constructor and tested our movie now, the bubbles would be all there but we wouldn’t see them because they would be beneath the button. Remember that each bubble is added to the effectContainer in the resetCircle method and that the effectContainer is masked so that the bubbles aren’t seen outside of the button.

    (Plus, if you tested the movie now you’d just get a compile-time error for not implementing the stopEffect method that is called when we create our bubbles.)

    
    
    private function playEffect():void {
    
    	for each( var tween:TweenMax in tweens ) {
    
    		tween.play();
    	}
    }
    
    private function stopEffect():void {
    
    	for each( var tween:TweenMax in tweens ) {
    
    		tween.pause();
    	}
    }
    

    Loop through the tweens array to play each tween and to pause each tween when needed. Very simple.

    Now add a call to the createEffect method and the playEffect method within the constructor. Test your movie. You should now have a beautiful display of bubbles. When you are finished remove the playEffect method from the constructor that you just added but keep the createEffect method.

    Step 17: Glowing Text

    Let’s add the glowing TextField to the button. We’re using a seperate TextField, effectTxt instead of txt, so that we can do a fading transition into the next state. We need an additional TextField for this. We also need another mask for our TextField just as we did with the first one.

    
    
    public function MyButton() {
    
    	super();
    	buttonMode = true;
    	mouseChildren = false;
    	_width = 100;
    
    	base = new RectangleShape();
    	base.height = BUTTON_HEIGHT;
    	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
    	base.fillGradientRotation = 90;
    	base.fillColors = [ 0xAAAAAA, 0x444444 ];
    	base.lineColors = [ 0x222222 ];
    	base.lineAlphas = [ .5 ];
    	base.lineRatios = [ 1 ];
    
    	ref = new RectangleShape();
    	ref.fillGradientRotation = 90;
    	ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
    	ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
    	ref.fillAlphas = [ 1, 0 ];
    	ref.lineColors = [ 0 ];
    	ref.lineAlphas = [ 0 ];
    	ref.lineRatios = [ 0 ];
    	ref.alpha = .5;
    	ref.x = ref.ellipseHeight / 2;
    	ref.width = _width - ref.height;
    
    	light = new RectangleShape();
    	light.copy( ref );
    	light.x = ref.x;
    	light.y = BUTTON_HEIGHT - light.height;
    	light.width = _width - light.height;
    	light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
    	light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
    	light.alpha = lightAlpha = .3;
    
    	txt = new TextField();
    	txt.selectable = false;
    	txt.type = "dynamic";
    	txt.wordWrap = false;
    	txt.multiline = false;
    	txt.autoSize = "left";
    	txt.defaultTextFormat = new TextFormat( null, 27 );
    	txt.textColor = 0x333333;
    	txt.text = "label";
    	txt.height = BUTTON_HEIGHT;
    
    	txtMask = new RectangleShape();
    	txtMask.copy( base );
    	txtMask.filters = [];
    	txt.mask = txtMask;
    
    	glow = new RectangleShape();
    	glow.copy( base );
    	glow.fillColors = [ 0xFFFFFF ];
    	glow.fillAlphas = [ 1 ];
    	glow.fillRatios = [ 0 ];
    	glow.lineColors = [ 0 ];
    	glow.lineAlphas = [ 0 ];
    	glow.lineRatios = [ 0 ];
    	glow.filters = [ new GlowFilter( 0x00BCE9, 1, 10, 10, 2, 3, false, false ), new GlowFilter( 0x00BCE9, 1, 20, 20, 2, 3, true ) ];
    
    	effectContainer = new Sprite();
    	effectContainer.cacheAsBitmap = true;
    
    	effectMask = new RectangleShape();
    	effectMask.copy( base );
    	effectMask.filters = [];
    	effectContainer.mask = effectMask;
    
    	effectTxt = new TextField();
    	effectTxt.selectable = false;
    	effectTxt.type = "dynamic";
    	effectTxt.wordWrap = false;
    	effectTxt.multiline = false;
    	effectTxt.autoSize = "left";
    	effectTxt.defaultTextFormat = new TextFormat( null, 27 );
    	effectTxt.textColor = 0x00BCE9;
    	effectTxt.text = "label";
    	effectTxt.filters = [ new GlowFilter( 0x00BCE9, 1, 16, 16, 2, 3 ) ];
    
    	effectTxtMask = new RectangleShape();
    	effectTxtMask.copy( base );
    	effectTxtMask.filters = [];
    	effectTxt.mask = effectTxtMask;
    
    	circleBlur = new BlurFilter( 5, 5, 3 );
    	circles = [];
    	tweens = [];
    
    	addChild( base );
    	addChild( light );
    	addChild( ref );
    	addChild( txt );
    	addChild( txtMask );
    	addChild( glow );
    	addChild( effectContainer );
    	addChild( effectMask );
    	addChild( effectTxt );
    	addChild( effectTxtMask );
    
    	createEffect();
    }
    

    Just another TextField with a glow filter. Again we will position the text fields later when we create the update method. Now you should have something that looks like this.

    Now that all of the elements for the over state have been generated, we only have one more task to complete. Next we position the contents of the button.

    Step 18: Positioning

    Encapsulated in our button class is a function that positions the button’s contents based on the current value of the _width property. The method I am referring to is the update method. Call the update method on the last line of code of the constructor method. Then create the update method.

    
    
    	addChild( effectTxt );
    	addChild( effectTxtMask );
    
    	createEffect();
    	update();
    }
    
    protected function update():void {
    
    	base.width = _width;
    	glow.width = _width;
    	ref.width = _width - ref.height;
    	light.width = _width - light.height;
    	txt.x = ( _width - txt.width ) / 2;
    	txt.y = ( BUTTON_HEIGHT - txt.height ) / 2;
    	effectTxt.x = txt.x;
    	effectTxt.y = txt.y;
    	effectMask.width = _width;
    	txtMask.width = _width;
    	effectTxtMask.width = _width;
    }
    

    Resize particalar objects and reposition others. Test the movie:

    We now have centered text. Set the alpha property of all of the effect base objects(effectContainer, effectTxt and glow) to zero. Re-test the movie and now you should see the original state of the button.

  10. Michael James Williams says:
    December 10, 2011 at 2:29 am

    As you may know, the Tuts+ network is accompanied by an online educational members-only site called Tuts+ Premium. We’re very excited to announce that Tuts+ Premium has received a huge upgrade, including a new library of courses, 27 top-selling educational eBooks, member forums, and a completely redesigned UI. You can check out all the changes at tutsplus.com (I recommend taking the tour) or read on to learn about what you will get from Tuts+ Premium.


    Library of Courses

    You’ve seen Sessions and series at Activetuts+ and on the other Tuts+ sites; the new Tuts+ Premium introduces courses.

    Would you like to learn how to design your first website in 30 days? Or get to grips with the languages of the web, HTML & CSS? Perhaps you’re already familiar with that, and you’re more interested in understanding the essentials of CSS3, or maybe you’d like to study something completely unrelated to web development, like using Photoshop to create concept art. Our new Tuts+ Premium courses will show you how. We’ll be adding new courses several times per month.


    45 Exclusive Flash and Browser App Tutorials

    Tuts+ Premium includes 45 (and counting) in-depth tutorials on browser app and game development, covering the same kinds of topics you’re used to from Activetuts+, but in much more detail:

    • Carlos Yanez has a set of tutorials explaining how to create various simple games from scratch – design and code
    • Jon Reid has written a great guide to an unusual topic: using the Kinect with the Flash Player
    • Mathias Johansson has created a brilliant tutorial explaining the basics of advanced body mechanics (for animation)
    • Daniel Branicki has shown how to create a Match-3 game in Flash and a 2D Portal-style game in Unity, in tutorials so big they each require multiple parts
    • …and there’s plenty more, on animation, game engine development, 3D user interfaces, and special effects.

      Every tutorial now has a free preview, so you can get a taste of what’s in store before you buy.


      My Thoughts

      Earlier this year, I got to manage the awesome team that migrated the tutorials from the old Tuts+ Premium system to this new one, so I’m very familiar with both systems and the content. I think it’s fair to say that the old system… had some flaws. It could be difficult to find tutorials unless you were looking for one specifically, and having to download and extract a ZIP file (which in some cases could be over 1GB) just to access the tut was a huge pain.

      The new Premium is better in so many ways. You can filter tutorials by topic, by difficulty, and by completion time – and search across the entire library – so it’s much easier to browse for and discover content. Reading tutorials and watching screencasts is much easier too; they’re all accessible in your browser, with an interface similar to the regular Tuts+ sites.

      And I must confess: before doing the migration, I didn’t realise how much great content there is on Premium. I don’t just mean the Flash and RIA Premium tutorials – although that selection is excellent, and becoming even better as we add more and more (you should see what we have planned!) – I mean all the content from the other Tuts+ sites that I wasn’t even aware of.

      For example, Aetuts+ has some excellent videos about animation, like The 12 Basic Principles of Animation, that are relevant to anyone doing animation, game design, or even flashy UI design. Cgtuts+ has some incredible series on modeling 3D objects, like this next-gen armoured car, which will be useful to anyone creating assets for a Unity project. And if you want to learn JavaScript, Nettuts+ has you covered.

      I’ve highlighted tutorials that are related to the topics we cover on Activetuts+, but if you want to branch out and learn something new, there’s plenty of opportunity to do that as well. Illustration, photography, digital audio, mobile app development… oh, and you have to check out Ed Lopez’s amazing digital painting tutorials.

      The new extras – forums, ebooks, courses – are all great, but to me, the appeal of Tuts+ Premium lies in its tutorials. Now, at last, those tutorials are easy to find and easy to read (or watch, for screencasts). That alone is worth the $19 a month entry price.


      Top-selling Educational eBooks

      Tuts+ Premium memberships now include 27 top-selling eBooks worth more than $440, including:

    • Freelance Confidential – $29 Free for Tuts+ Premium members
    • Successful Facebook Marketing – $24 Free for Tuts+ Premium members
    • How to Be a Rockstar Freelancer – $29 Free for Tuts+ Premium members
    • Twitter Up Your Business – $8 Free for Tuts+ Premium members
    • How to Build a Successful Blog Business – $39 Free for Tuts+ Premium members
    • How to Take Great Photos – $9 Free for Tuts+ Premium members
    • … and lots more!

    Beautiful Redesign

    The new Tuts+ Premium was designed by Orman Clark and Envato designer Jacob Zinman-Jeanes. And, thank you to Simplifilm, who make a mean product demo video!

    Take a Tour of Tuts+ Premium


  11. 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
    • Workshop Coding Challenge: Fix This Breakout Game
    • Enable the Latest AIR SDK in Flash Professional CS5.5+
    • Quick Tip: Versioning Your Files With Dropbox (via Webdesigntuts+)
    • Workshop: Nuclear Outrun – Critique
    • Understanding Variables, Arrays, Loops, and Null: The Post-it Note Analogy
    Tag Cloud
    2011 ActionScript Active Activetuts+ Adobe animation Basic Basix Best Build Button Character Create Creating Critique Custom design Effect Effects Files Flash from Game Guide HTML5 Introduction Macromedia Motion Muzzle part Player Premium Professional Quick Silverlight Simple Text Tool Tutorial Tuts+ Tween Using Video website Workshop
    About Our Site:

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

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

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

    Blogroll

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

    Meta

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

    Archives

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