Easily Create Souped-Up Flash Text Fields With TextArea
In this tutorial I’ll walk you through the steps required to install and use the TextArea component as an alternative to Flash’s native TextField class, and show you how to detect mouse roll over/out events on hyperlinks. I’ll also talk about how you can call custom functions and pass different data types as arguments.
Background
The native TextField class was the first to support text scripts in Flash projects. With TextField, you could support dynamic and static text, as well as the input type to allow user interactivity. It also supported a (very limited) selection of HTML tags for styling your scripts – but when comparing this narrow availability of HTML support in TextField to what is possible with regular HTML files being used within browsers, Flash developers felt the extreme lack of flexibility when dealing with text.
In 2009 when TLFTextField was introduced, developers were hoping to see some solutions – but these didn’t appear. Today, with the TextArea class, you can do what you always wanted with your text blocks. Functionalities like detecting roll over/out on href links, calling custom functions from text blocks, creating anchor links, loading custom created tags like video players, slideshow, and buttons: these are all now possible with TextArea.
Final Result Preview
The following simple no-frills demo will present how custom functions are called on hyperlinks. This is what you’ll build in the next 30 minutes:
Step 1: Set Up the Environment
TextArea can be used in any IDE that compiles AS3 – like Flash Builder, CS pro versions and FlashDevelop – which means it’ll work across Flash platform (in Flex, AIR and AS3-only web projects). Different IDEs each have a somehow similar but unique approach to how you compile your project, and due to this diversity it’s sometimes frustrating, especially for beginners, to work with AS3 tutorials because the author may prefer Flash Builder while the learner is accustomed to work with the CS IDE.
To solve this problem, I will try to explain the usage of TextArea independent of the IDE. So, the first step is to set up your environment. No matter which IDE you’re using, just open it and create a new AS3 project, then save it somewhere on your computer.
Create a document class, name it Main.as, and add a trace call to output Hello World.
package
{
import flash.display.MovieClip
public class Main extends MovieClip
{
public function Main():void
{
trace("Hello World")
}
}
}
Step 2: Download TextArea
TextArea is free to download and to use but be sure to read the license agreements here. Head to doitflash.com and find the download button at the bottom of the home page to download TextArea classes.
Extract the zip file you downloaded, TextArea.zip, to your computer, go to the folder TextArea/Src, and copy the com folder then to the same directory as your document class, Main.as.
By copying the com folder to where you have your project document class, you are letting the IDE find TextArea classes only in this specific project. Alternatively, you could copy the classes to your global class path so that it will always be available to all your projects – to find out more, read How To Use an External Library in Your Flash Projects.
Step 3: Initializing TextArea
After downloading and installing the TextArea, it’s time to initialize it. First you need to import the required classes to the Main class.
import com.doitflash.text.TextArea;
Then remove the hello world trace function and enter the following instead.
var _textArea:TextArea = new TextArea(); _textArea.wordWrap= true; _textArea.multiline = true; _textArea.htmlText = "Initialize TextArea just like you used to initialize TextField."; this.addChild(_textArea);
Test your movie and this time instead of outputting hello world, you’ll see a text field (but not a TextField!) created for you:

As you can see, TextArea works exactly like the native TextField class. All the different settings that you could apply to TextField are true for TextArea also; it’s basically an extension to TextField so it will do everything TextField does, plus more. I’ll talk about these extra features in the next sections.
Step 4: Feeding TextArea With an XML File
To make this tutorial as informative as possible and to make it useable for real world practices, let’s try to feed the TextArea instance with data from an external XML file.
This procress will again be similar to how you load XML data into TextField. First, create your XML file and place it where you have the published SWF file from the previous steps. Make the XML look like the below and save it as “data.xml”:
<?xml version="1.0" encoding="UTF-8"?> <data> <![CDATA[ <p align="left"><font face="Tahoma" size="13" color="#333333"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam cursus. Morbi ut mi. Nullam enim leo, egestas id, condimentum at, laoreet mattis, massa. </font></p> ]]> </data>
(So that XML contains HTML in a CDATA section.)
Now get back to your Main.as, which should look like the following:
package
{
import flash.display.MovieClip
import com.doitflash.text.TextArea;
public class Main extends MovieClip
{
public function Main():void
{
var _textArea:TextArea = new TextArea();
_textArea.wordWrap = true;
_textArea.multiline = true;
_textArea.htmlText = "Initialize TextArea just like you used to initialize TextField.";
this.addChild(_textArea);
}
}
}
Add the required imports for xml loading process.
import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest;
Then replace the whole Main() function with this.
public function Main():void
{
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onXmlLoaded);
loader.load(new URLRequest("data.xml"));
function onXmlLoaded(e:Event):void
{
var xml:XML = new XML(e.currentTarget.data);
var _textArea:TextArea = new TextArea();
_textArea.wordWrap = true;
_textArea.multiline = true;
_textArea.width = 400;
_textArea.height = 200;
_textArea.condenseWhite = true;
_textArea.htmlText = xml.text();
addChild(_textArea);
}
}
The above code loads data.xml – there’s no difference from how you would have done it with a TextField so far.
Step 5: Detecting Mouse Rollover/Rollout
To use the specific features of TextArea, you need to specify a few extra settings when initializing it.
The first and the most important thing to remember about using TextArea is that you should use the fmlText method for sending text scripts into the instance rather than using the classic htmlText. The fmlText method will parse scripts using a different approach than htmlText; it stands for Flash Markup Language Text.
So, in your test project, replace htmlText with fmlText like below.
_textArea.fmlText = xml.text();
The next thing to do is create two custom functions in your document class, Main.as, which will be called when you rollover or rollout a hyperlink (which we will build later in data.xml). For the sake of this tutorial, these two functions will just trace some outputs, but in the real world, you could do anything you want with these functions – like, say, opening a tooltip window.
public function funcOnOver():void
{
trace("rollOver");
}
public function funcOnOut():void
{
trace("rollOut");
}
You should also set some settings while initializing the TextArea instance. Add these lines just after you initialize TextArea.
_textArea.holder = refToThis; // indicates the location where you are adding TextArea to stage _textArea.client = refToThis; // must be the location where you have your "allowedFunctions" saved _textArea.mouseRollOverEnabled = true; // enables mouse rollover detection _textArea.funcSecurity = true; // makes sure only function names in "allowedFunctions" are accessible _textArea.allowedFunctions(funcOnOver, funcOnOut);
Also add the following line to the beginning of the Main() function.
var refToThis:Object = this;
To make sure you have written the code in Main.as correctly, below is how your file should look up to now.
package
{
import flash.display.MovieClip
import com.doitflash.text.TextArea;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class Main extends MovieClip
{
public function Main():void
{
var refToThis:Object = this;
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onXmlLoaded);
loader.load(new URLRequest("data.xml"));
function onXmlLoaded(e:Event):void
{
var xml:XML = new XML(e.currentTarget.data);
var _textArea:TextArea = new TextArea();
_textArea.holder = refToThis; // indicates the location where you are adding TextArea to stage
_textArea.client = refToThis; // must be the location where you have your "allowedFunctions" saved
_textArea.mouseRollOverEnabled = true; // enables mouse rollover detection
_textArea.funcSecurity = true; // makes sure only function names in "allowedFunctions" are accessible
_textArea.allowedFunctions(funcOnOver, funcOnOut);
_textArea.wordWrap = true;
_textArea.multiline = true;
_textArea.width = 400;
_textArea.height = 200;
_textArea.condenseWhite = true;
_textArea.fmlText = xml.text();
addChild(_textArea);
}
}
public function funcOnOver():void
{
trace("rollOver");
}
public function funcOnOut():void
{
trace("rollOut");
}
}
}
That’s pretty much everything you need to do in your .as file; and the rest will be done in the XML but before we go to XML and create a hyperlink, let’s talk a bit about the above settings.
First we have the holder property which is something that you won’t use in this article but when you go deeper into TextArea to create custom html tags you will need this a lot; for the sake of this tutorial, it’s sufficient for you to know that this property saves the location where you are adding the TextArea instance into the stage.
Then we have the client property. This is the location of – or better to say, this is a reference to – a class where you save all your allowed functions. In this example we use Main.as as the client, but if you have a long list of functions that want to give them the permission to be called from your text scripts, you may prefer creating a separate class for that purpose.
We also have the mouseRollOverEnabled property which is set to false by default for performance reasons. If you want to detect mouse roll over/out on your hyperlinks, you must make sure you enable this property.
Then we have two security properties: allowedFunctions and funcSecurity. These properties will let you restrict the called functions to the specific ones mentioned in the allowedFunctions method.
Okay, to see the magic, get back to data.xml and and add the following line somewhere inside the CDATA section:
Here's a <u><a href='onMouseOver:funcOnOver();onMouseOut:funcOnOut()'>SAMPLE LINK</a></u>.
As you see you have created two function calls (one on mouse rollover, one on mouse rollout) and you can do whatever you like with these functions inside your AS3 project.
But this is not all! In the next section I’ll talk about how you can call custom functions and pass different types of data as arguments.
Step 6: Pass Arguments to Functions
Up to now, you have learned how to set the TextArea instance ready for accepting function calls from HTML content which can be placed in external sources like XML. Now we’re going to send different types of arguments along with the calls.
We can send array, object and simple string types. Try adding the following hyperlink somewhere inside the CDATA tag in your XML file:
<u><a href='event:func1()'>SIMPLE CALL</a></u>.<br />
<u><a href='event:func2(some string)'>SEND STRING</a></u>.<br />
<u><a href='event:func3([0,1,2,3,4])'>SEND ARRAY</a></u>.<br />
<u><a href='event:func4({var1:val1;var2:val2})'>SEND OBJECT</a></u>.<br />
<u><a href='event:func5(string,[0,1,2],{var1:val1;var2:val2})'>SEND MIXED ARGUMENTS</a></u>.<br />
This will create five function calls in your AS3 project; each function demonstrates how you can send different types of arguments. But remember that this will not work until you actually create these functions inside your AS3 project. To do that, simply add these functions along with the funcOnOver() and funcOnOut() functions that you had previously:
public function func1():void
{
trace("no arguments sent");
}
public function func2($str:String):void
{
trace("arguments >> " + $str);
}
public function func3($arr:Array):void
{
trace("arguments >> " + $arr);
}
public function func4($obj:Object):void
{
trace("arguments >> " + $obj);
}
public function func5($str:String, $arr:Array, $obj:Object):void
{
trace("arguments >> " + $str);
trace("arguments >> " + $arr);
trace("arguments >> " + $obj);
}
Now you have the calls in XML and the functions are also available in the AS3 project; all that’s left is to give the usage permission to the TextArea instance. Modify the allowedFunctions method of TextArea as so:
_textArea.allowedFunctions(funcOnOver, funcOnOut, func1, func2, func3, func4, func5);
Now publish and test your project and try clicking the hyperlinks you created.
Congratulations, you have now learned how to enable mouse rollover and rollout in your text fields, and you know how to create custom functions and call them from within your text blocks.
Conclusion
TextArea extends TextField, adds only 6kb to your project, and can be used as an alternative to TextField. In this tutorial you learned how to initialize TextArea to create simple hyperlinks which can call custom functions inside your AS3 project, and you also learned how to enable mouse rollover and rollout detection on hyperlinks that can call custom functions.
There are many things you can do with these features, like open a tooltip when rolling over a certain hyperlink or create links which call a custom function in your project to navigate through your application pages easier.
I hope you find this tutorial (and TextArea itself) useful!
View full post on Activetuts+

In this tutorial I’ll walk you through the steps required to install and use the TextArea component as an alternative to Flash’s native TextField class, and show you how to detect mouse roll over/out events on hyperlinks. I’ll also talk about how you can call custom functions and pass different data types as arguments.
Background
The native TextField class was the first to support text scripts in Flash projects. With TextField, you could support dynamic and static text, as well as the input type to allow user interactivity. It also supported a (very limited) selection of HTML tags for styling your scripts – but when comparing this narrow availability of HTML support in TextField to what is possible with regular HTML files being used within browsers, Flash developers felt the extreme lack of flexibility when dealing with text.
In 2009 when TLFTextField was introduced, developers were hoping to see some solutions – but these didn’t appear. Today, with the TextArea class, you can do what you always wanted with your text blocks. Functionalities like detecting roll over/out on href links, calling custom functions from text blocks, creating anchor links, loading custom created tags like video players, slideshow, and buttons: these are all now possible with TextArea.
Final Result Preview
The following simple no-frills demo will present how custom functions are called on hyperlinks. This is what you’ll build in the next 30 minutes:
Step 1: Set Up the Environment
TextArea can be used in any IDE that compiles AS3 – like Flash Builder, CS pro versions and FlashDevelop – which means it’ll work across Flash platform (in Flex, AIR and AS3-only web projects). Different IDEs each have a somehow similar but unique approach to how you compile your project, and due to this diversity it’s sometimes frustrating, especially for beginners, to work with AS3 tutorials because the author may prefer Flash Builder while the learner is accustomed to work with the CS IDE.
To solve this problem, I will try to explain the usage of TextArea independent of the IDE. So, the first step is to set up your environment. No matter which IDE you’re using, just open it and create a new AS3 project, then save it somewhere on your computer.
Create a document class, name it Main.as, and add a trace call to output Hello World.
package { import flash.display.MovieClip public class Main extends MovieClip { public function Main():void { trace("Hello World") } } }Step 2: Download TextArea
TextArea is free to download and to use but be sure to read the license agreements here. Head to doitflash.com and find the download button at the bottom of the home page to download TextArea classes.
Extract the zip file you downloaded, TextArea.zip, to your computer, go to the folder TextArea/Src, and copy the com folder then to the same directory as your document class, Main.as.
By copying the com folder to where you have your project document class, you are letting the IDE find TextArea classes only in this specific project. Alternatively, you could copy the classes to your global class path so that it will always be available to all your projects – to find out more, read How To Use an External Library in Your Flash Projects.
Step 3: Initializing TextArea
After downloading and installing the TextArea, it’s time to initialize it. First you need to import the required classes to the Main class.
Then remove the hello world trace function and enter the following instead.
Test your movie and this time instead of outputting hello world, you’ll see a text field (but not a
TextField!) created for you:As you can see, TextArea works exactly like the native TextField class. All the different settings that you could apply to TextField are true for TextArea also; it’s basically an extension to TextField so it will do everything TextField does, plus more. I’ll talk about these extra features in the next sections.
Step 4: Feeding TextArea With an XML File
To make this tutorial as informative as possible and to make it useable for real world practices, let’s try to feed the TextArea instance with data from an external XML file.
This procress will again be similar to how you load XML data into TextField. First, create your XML file and place it where you have the published SWF file from the previous steps. Make the XML look like the below and save it as “data.xml”:
(So that XML contains HTML in a CDATA section.)
Now get back to your Main.as, which should look like the following:
package { import flash.display.MovieClip import com.doitflash.text.TextArea; public class Main extends MovieClip { public function Main():void { var _textArea:TextArea = new TextArea(); _textArea.wordWrap = true; _textArea.multiline = true; _textArea.htmlText = "Initialize TextArea just like you used to initialize TextField."; this.addChild(_textArea); } } }Add the required imports for xml loading process.
Then replace the whole Main() function with this.
public function Main():void { var loader:URLLoader = new URLLoader(); loader.addEventListener(Event.COMPLETE, onXmlLoaded); loader.load(new URLRequest("data.xml")); function onXmlLoaded(e:Event):void { var xml:XML = new XML(e.currentTarget.data); var _textArea:TextArea = new TextArea(); _textArea.wordWrap = true; _textArea.multiline = true; _textArea.width = 400; _textArea.height = 200; _textArea.condenseWhite = true; _textArea.htmlText = xml.text(); addChild(_textArea); } }The above code loads data.xml – there’s no difference from how you would have done it with a TextField so far.
Step 5: Detecting Mouse Rollover/Rollout
To use the specific features of TextArea, you need to specify a few extra settings when initializing it.
The first and the most important thing to remember about using TextArea is that you should use the
fmlTextmethod for sending text scripts into the instance rather than using the classichtmlText. ThefmlTextmethod will parse scripts using a different approach thanhtmlText; it stands for Flash Markup Language Text.So, in your test project, replace
htmlTextwithfmlTextlike below.The next thing to do is create two custom functions in your document class,
Main.as, which will be called when you rollover or rollout a hyperlink (which we will build later in data.xml). For the sake of this tutorial, these two functions will just trace some outputs, but in the real world, you could do anything you want with these functions – like, say, opening a tooltip window.public function funcOnOver():void { trace("rollOver"); } public function funcOnOut():void { trace("rollOut"); }You should also set some settings while initializing the TextArea instance. Add these lines just after you initialize TextArea.
Also add the following line to the beginning of the Main() function.
To make sure you have written the code in Main.as correctly, below is how your file should look up to now.
package { import flash.display.MovieClip import com.doitflash.text.TextArea; import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest; public class Main extends MovieClip { public function Main():void { var refToThis:Object = this; var loader:URLLoader = new URLLoader(); loader.addEventListener(Event.COMPLETE, onXmlLoaded); loader.load(new URLRequest("data.xml")); function onXmlLoaded(e:Event):void { var xml:XML = new XML(e.currentTarget.data); var _textArea:TextArea = new TextArea(); _textArea.holder = refToThis; // indicates the location where you are adding TextArea to stage _textArea.client = refToThis; // must be the location where you have your "allowedFunctions" saved _textArea.mouseRollOverEnabled = true; // enables mouse rollover detection _textArea.funcSecurity = true; // makes sure only function names in "allowedFunctions" are accessible _textArea.allowedFunctions(funcOnOver, funcOnOut); _textArea.wordWrap = true; _textArea.multiline = true; _textArea.width = 400; _textArea.height = 200; _textArea.condenseWhite = true; _textArea.fmlText = xml.text(); addChild(_textArea); } } public function funcOnOver():void { trace("rollOver"); } public function funcOnOut():void { trace("rollOut"); } } }That’s pretty much everything you need to do in your .as file; and the rest will be done in the XML but before we go to XML and create a hyperlink, let’s talk a bit about the above settings.
First we have the holder property which is something that you won’t use in this article but when you go deeper into TextArea to create custom html tags you will need this a lot; for the sake of this tutorial, it’s sufficient for you to know that this property saves the location where you are adding the TextArea instance into the stage.
Then we have the client property. This is the location of – or better to say, this is a reference to – a class where you save all your allowed functions. In this example we use Main.as as the client, but if you have a long list of functions that want to give them the permission to be called from your text scripts, you may prefer creating a separate class for that purpose.
We also have the mouseRollOverEnabled property which is set to
falseby default for performance reasons. If you want to detect mouse roll over/out on your hyperlinks, you must make sure you enable this property.Then we have two security properties: allowedFunctions and funcSecurity. These properties will let you restrict the called functions to the specific ones mentioned in the allowedFunctions method.
Okay, to see the magic, get back to data.xml and and add the following line somewhere inside the CDATA section:
As you see you have created two function calls (one on mouse rollover, one on mouse rollout) and you can do whatever you like with these functions inside your AS3 project.
But this is not all! In the next section I’ll talk about how you can call custom functions and pass different types of data as arguments.
Step 6: Pass Arguments to Functions
Up to now, you have learned how to set the TextArea instance ready for accepting function calls from HTML content which can be placed in external sources like XML. Now we’re going to send different types of arguments along with the calls.
We can send array, object and simple string types. Try adding the following hyperlink somewhere inside the CDATA tag in your XML file:
<u><a href='event:func1()'>SIMPLE CALL</a></u>.<br /> <u><a href='event:func2(some string)'>SEND STRING</a></u>.<br /> <u><a href='event:func3([0,1,2,3,4])'>SEND ARRAY</a></u>.<br /> <u><a href='event:func4({var1:val1;var2:val2})'>SEND OBJECT</a></u>.<br /> <u><a href='event:func5(string,[0,1,2],{var1:val1;var2:val2})'>SEND MIXED ARGUMENTS</a></u>.<br />This will create five function calls in your AS3 project; each function demonstrates how you can send different types of arguments. But remember that this will not work until you actually create these functions inside your AS3 project. To do that, simply add these functions along with the
funcOnOver()andfuncOnOut()functions that you had previously:public function func1():void { trace("no arguments sent"); } public function func2($str:String):void { trace("arguments >> " + $str); } public function func3($arr:Array):void { trace("arguments >> " + $arr); } public function func4($obj:Object):void { trace("arguments >> " + $obj); } public function func5($str:String, $arr:Array, $obj:Object):void { trace("arguments >> " + $str); trace("arguments >> " + $arr); trace("arguments >> " + $obj); }Now you have the calls in XML and the functions are also available in the AS3 project; all that’s left is to give the usage permission to the TextArea instance. Modify the allowedFunctions method of TextArea as so:
Now publish and test your project and try clicking the hyperlinks you created.
Congratulations, you have now learned how to enable mouse rollover and rollout in your text fields, and you know how to create custom functions and call them from within your text blocks.
Conclusion
TextArea extends TextField, adds only 6kb to your project, and can be used as an alternative to TextField. In this tutorial you learned how to initialize TextArea to create simple hyperlinks which can call custom functions inside your AS3 project, and you also learned how to enable mouse rollover and rollout detection on hyperlinks that can call custom functions.
There are many things you can do with these features, like open a tooltip when rolling over a certain hyperlink or create links which call a custom function in your project to navigate through your application pages easier.
I hope you find this tutorial (and TextArea itself) useful!
In the first part of this series, I introduced a class to handle single mouse stroke detection:
MGesture. This tutorial takes it a step further, by detecting a sequence of strokes.We’ll be using the class
GManagerfor this, in tandem withMGesture. After briefing throughGManagerfunctionality, an application demonstrating its use will be developed.Final Result Preview
Let’s take a look at the final result we will be working towards. To use the Flash presentation below, use your mouse to perform the gesture as indicated by the arrow in the top left corner. Gesture by pressing the left mouse button, moving the mouse while holding the button, and then releasing it.
Step 1: Recap Direction Numbering
First step, a revision on integers used to represent different directions from Part 1. Hopefully, you can form a mental picture of the diagram above as we shall refer to it heavily throughout this tutorial.
Step 2: Strokes Detected
As user makes a gesture by any pointing devices (mouse, tablet pen, etc), the vectors successfully detected over time actually form a series of integers. Refer to diagram below.
Notice the unique integers in the sequence are 0, 4, 1. However, I shall say unique integers are 0, 1. Lets face it: it’s difficult to make an accurate stroke on my Bamboo tablet, and even more so with a mouse. Errors are inevitable. Our algorithm should then be based upon the high repetition of integers in a continuous string. They are 0, 1 here – 4 is probably due to inaccurate stroke. Therefore, this gesture can be uniquely identified as a sequence of 0, then 1.
I’ve included another few gestures with their accompanying unique sequences below.
Step 3: Introducing
GManagerThe purpose of this class is simple:
Developer has to define a set of stroke sequences to detect initially. Once done, event listeners to capture user gesture at runtime can be programmed. If the current gesture’s sequence successfully matches any one sequence in the predefined set, different operations can then be carried out.
Step 4: Variables
GManagerhas the following variables:gestSeqVector.<Vector.<int>>gestNameVector.<String>strokesVector.<int>gestCurrent‘s strokes when compared with stroke sequence.gestCurrentVector.<int>_orderBooleangestSeqshould be detected in order.orderCurrentint_orderis turned on; starts at 0.Step 5: Methods
Methods in
GManagerare as below:GManagergestSeqandgestName,strokesinitialisedregisterVector.<int>, String, intremoveintremoveAllstartgestCurrentpopulateintgestCurrentwith detected strokes (singular)tracerVector.<int>gestCurrentfor debugging purposes.dropStrokesVector.<int>, intVector.<int>gestCurrent. Keep mains and diagonals (0), keep only mains (1), keep only diagonals (2). (Part 3 will further explain its use.)dropDuplicatesVector.<int>, intVector.<int>duplicates. Input minimum duplicates (apart from self) to be considered valid stroke
checkMatchintintgestSeqmatches withgestCurrentendArrayArraywith index of matchedsequence in
gestSeqand its name ingestNameProperties of
GManagerare as below:useOrdergestSeqis to be detected in orderlengthgestSeqStep 6: Register Predefined Stroke Sequences
As mentioned, the first step is to register unique stroke sequences that the entered gesture can be compared against. The constructor initates variables needed (highlighted) and methods that follow registers into and removes from predefined stroke sequences.
/** * Constructor to initiate gestSeq, stokes, gestName */ public function GManager(){ gestSeq = new Vector.<Vector.<int>>; gestName = new Vector.<String>; strokes = new Vector.<int>; } /** * Method to register a set/ sequence of gesture * @param sequence Numerical representation of gesture sequence * @param identifier Name representation of gesture * @param allowed Stokes allowed: Both (0), main four (1), diagonals (2) */ public function register(sequence:Vector.<int>, name:String, onlyStrokes:int = 0):void { gestSeq.push(sequence); gestName.push(name); strokes.push(onlyStrokes); } /** * Method to remove a specific set of gesture * @param selectSet Selected sequence to remove */ public function remove(selectSet:int):void { gestSeq.splice(selectSet, 1); gestName.splice(selectSet, 1); strokes.splice(selectSet, 1); } /** * Method to remove all predefined gestures. */ public function removeAll():void { gestSeq = new Vector.<Vector.<int>>; gestName = new Vector.<String>; strokes = new Vector.<int>; }Step 7: Properties
Below are the properties specifically for set holding stroke seqeunces,
gestSeq:/** * Property to get total sets of predefined gestures */ public function get length ():int { return gestSeq.length; } /** * Property to get current setting on sequential gesture detection */ public function get useOrder():Boolean { return _order; } /** * Property to determine whether sets of predefined gestures should be detected sequentially */ public function set useOrder(value:Boolean):void { _order = value; }Step 8: Record Current Stroke Sequence
After registering stroke sequences to detect against, we can prepare
gestCurrentand record consequtive valid singular strokes into it. Methods below will provision for it.Traceris a method to trace the current gesture’s sequence./** * Method to start recording current set of gesture made */ public function start():void { gestCurrent = new Vector.<int>; } /** * Method to populate gesture into current set of gesture * @param gestureCode Gesture detected from MGesture */ public function populate (gestureCode:int):void { //Accept only valid singular gesture (0~8) into current sequence if(gestureCode > -1) gestCurrent.push(gestureCode); } /** * Method used for debugging. Traces gestCurrent */ public function tracer():Vector.<int> { return gestCurrent; trace(gestCurrent); }Step 9: Looking into
gestCurrentBy now, we can already write a program to check out current gesture’s sequence as mentioned in Step 2. You may download the source and look at the class
CheckOut2. Turn on your Output panel in FlashDevelop to view the sequence of integers committed by your current gesture.I’ve also included a demo of it below and placed a
TextFieldto display the sequence instead of the Output panel in FlashDevelop.Step 10: Implementation of
CheckOut2I have included source code of
checkOut2as below. Its not tough to understand the logic provided you have understood how event handlers are assigned. (Read this tutorial to find out more about event handlers.) I’ve also highlighted important points whereGManager‘s methods are being used.public class CheckOut2 extends Sprite { private var ges:MGesture; //instance of singular gesture detection private var gesMan:GManager; //instance of sequence gesture detectio private var t:TextField; public function CheckOut2() { //initiating MGesture to allow singular gesture detection ges = new MGesture(stage); //initiating GManager to allow sequential gesture detection gesMan = new GManager(); t = new TextField() t.x = 50; t.y = 50; t.autoSize = TextFieldAutoSize.LEFT; addChild(t); stage.addEventListener(MouseEvent.MOUSE_DOWN, start); stage.addEventListener(MouseEvent.MOUSE_UP, end); } private function start(e:MouseEvent):void { //Start detecting singular and sequential gesture ges.start(); gesMan.start(); stage.addEventListener(MouseEvent.MOUSE_MOVE, check); //Start drawing gesture graphics.clear(); graphics.lineStyle(3); graphics.moveTo(mouseX, mouseY); } private function check(e:MouseEvent):void { gesMan.populate(ges.evalDirections()); //Feed singular gesture into a sequence graphics.lineTo(mouseX, mouseY) //Drawing gesture } private function end(e:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_MOVE, check); t.text = gesMan.tracer().toString() } }Step 11: Clean Up
gestCurrentof Unnecessary StrokesCleaning up strokes in current gesture is important, as there are:
I have divided the clean-up job into two phases, specifically
dropStrokesanddropDuplicates.dropStrokeseliminates strokes that made it difficult to detect of gestures. (This feature will be explained in detail in Part 3 when we detect alphabetical letters.)dropDuplicateseliminates duplicates and invalid strokes.dropStrokeswill only keep strokes ingestCurrentaccording to the third paramenter,onlyStrokes, inregister. It is defined when we register the gesture sequences initially. For further understanding, again, watch out for Part 3. But for now, just keep it at the back of your head. In fact, this tutorial does not make use of this feature just yet./** * Method to rid irrelevant strokes based upon condition * @param strokesCondition * @return Vector of */ private function dropStrokes(inputArray:Vector.<int>, strokesCondition:int):Vector.<int> { var xDiagonals:Vector.<int> = inputArray.slice(0,inputArray.length); //Keep mains only if (strokesCondition == 1) { for (var i:int = 0; i < xDiagonals.length; i++) { if (xDiagonals[i] > 3) { xDiagonals.splice(i, 1); i-- } } } else if (strokesCondition == 2) { for (var j:int = 0; j < xDiagonals.length; j++) { if (xDiagonals[j] <4) { xDiagonals.splice(j, 1); j-- } } } return xDiagonals }Step 12: Clean Up
gestCurrentSwipe left-to-right to go to the next frame.
The second phase of clean up is to rid the duplicate and invalid strokes as mentioned in Step 2. The implementation is written below.
I’ve placed a Flash presentation above to ease your understanding of the algorithm. Make a right gesture using mouse to go to next frame, make a left to go back to previous frame. Up gesture brings you to the final frame, down gesture brings you to the first frame.
/** * Method to rid duplicates and possible mistaken gestures * @param minDuplicates Repetition to be considered high repetition * @return Vector array w/o duplicates and possible mistaken gestures */ private function dropDuplicates (inputArray:Vector.<int>, minDuplicates:int = 1):Vector.<int> { //Append end of line indicator to integer array var xDuplicates:Vector.<int> = inputArray.slice(0,inputArray.length); xDuplicates.push( -1); //Initiate variables var count:int = 1; var keepIndex:int = 0; //Ripping duplicates and invalid moves for (var i:int = 0; i < xDuplicates.length - 1; i++) { if (xDuplicates[i] == xDuplicates[i + 1]) count ++ else{ if (count > minDuplicates) { xDuplicates.splice(keepIndex, count - 1) keepIndex++ i = keepIndex count = 1 } else xDuplicates.splice(keepIndex, minDuplicates) i-- } } xDuplicates.splice(xDuplicates.length - 1, 1); return xDuplicates; }Step 13: Check for a Match
After trimming down
gesCurrent, our next task is to find a proper match in the set of predefined gesture sequences. We can verify match between current gesture and a member of predefined gestures usingcheckMatch. Input the index ofgestSeqyou would like to check match withgestCurrent. A return value of-1indicates no match; the index ofgestSeqis matched otherwise./** * Method to check if gestCurrent matches with gestSeq * @param index Member of gestSeq * @return Match (1) or fail (-1) */ private function checkMatch(index:int):int { //Pessimistic search, assumes not found initially var matched:int = -1; //clean input first var cleaned:Vector.<int> = dropStrokes(gestCurrent, strokes[index]); trace(cleaned, " xstrokes"); cleaned = dropDuplicates(cleaned);trace(cleaned," xduplicates") //Check only those of same length if (cleaned.length == gestSeq[index].length) { var counter:int = cleaned.length; //Scroll through each integer of selected predefined gesture for (var member:int = 0; member < cleaned.length; member++) { if (cleaned[member] == gestSeq[index][member]) counter--; else break; } //if all integers matched, current index of gestSeq matches gestCurrent if (counter == 0 ) matched = index; } return matched; }Step 14: Output the Result
Finally, we can output the result. The result will be based upon whether
_orderis turned on or not. We check match betweengestCurrentwith currentgestSeqonly if_orderis turned on, otherwise we will need to search for match with any member ingestSeq.Regardless of the search outcome, we need to output the result. Search result will be
-1if there’s no successful match; if there’s a match, an array of stroke index coupled with its name will be returned. The result is-2ifgestSeqis empty./** * Method to evaluate gesture according to preferred approach (in sequential order or not) * @return No predefined gestures (-2), No match of gesture (-1), array with index of match and its description */ public function end():Array { //Pessimistic search, -2 indicates that there are no predefined gesture var result:Array = [ -2, "No predefined gestures"]; //If there are predefined gestures if (gestSeq.length > 0) { //Find the match in order if (_order) { if (checkMatch(orderCurrent) > -1) { result = [orderCurrent, gestName[orderCurrent]]; orderCurrent++; } } //Find a match in no specific order else if (!_order) { //Scroll through all gestures for (var i:int = 0; i < gestSeq.length; i++) { if (checkMatch(i) > -1) { result = [i, gestName[i]]; } } } //Handle when cant find else { result = [ -1, "Gesture is invalid."] } } return result }Step 15: Prepare Graphical Assets in Flash
With Step 14 we completed
GManager. We need to create graphical assets next. I have created the graphical assets in Flash Pro and will export them in .swc format. Press Ctrl + Shift + F12 to pop the Publish Setting window out in Flash and check “Export SWC” under Flash tab. I’ve made my assets available for download but feel free to develop your own.Step 16: Importing Assets Into FlashDevelop
Bring your SWC into FlashDevelop’s
libfolder as shown above. Create a class named “Main2″ in FlashDevelop and instantiate the MovieClip that holds the graphics. I’ve highlighted the relevant ActionScript below.private var ges:MGesture; private var gesMan:GManager; private var a:Arrows; private var seq:Boolean = false; public function Main2() { //Importing graphics in form of movieclip a = new Arrows(); a.stop(); a.x = 50; a.y = 50; addChild(a);Step 17: Register Corresponding Gestures
We shall register our gesture sequences in the order that graphics are arranged in our published MovieClip. We do so to make easy scrolling of frames once the result has been attained. Note as well that I have highlighted line 33 of the implementation; you may uncomment this to in my source file to see matching done in order.
public function Main2() { //Importing graphics in form of movieclip a = new Arrows(); a.stop(); a.x = 50; a.y = 50; addChild(a); //initiating MGesture to allow singular gesture detection ges = new MGesture(stage); //initiating GManager to allow sequential gesture detection gesMan = new GManager(); //this.seq = true; //Detecting gestures in sequence if (seq) { a.gotoAndStop(2); gesMan.useSeq = true; } //Register gesture sequences in line with frames //Register gesture sequences in line with frames gesMan.register(new < int > [2, 1], "2 Stroke Down, CCW"); gesMan.register(new < int > [1, 0], "2 Stroke Right, CCW"); gesMan.register(new < int > [0, 3], "2 Stroke Up, CCW"); gesMan.register(new < int > [3, 2], "2 Stroke Left, CCW"); gesMan.register(new < int > [3, 2, 1], "3 Stroke Down, CCW"); gesMan.register(new < int > [2, 1, 0], "3 Stroke Right, CCW"); gesMan.register(new < int > [1, 0, 3], "3 Stroke Up, CCW"); gesMan.register(new < int > [0, 3, 2], "3 Stroke Left, CCW"); gesMan.register(new < int > [3, 0], "2 Stroke Right, CW"); gesMan.register(new < int > [0, 1], "2 Stroke Down, CW"); gesMan.register(new < int > [1, 2], "2 Stroke Left, CW"); gesMan.register(new < int > [2, 3], "2 Stroke Up, CW"); gesMan.register(new < int > [2, 3, 0], "3 Stroke Right, CW"); gesMan.register(new < int > [3, 0, 1], "3 Stroke Down, CW"); gesMan.register(new < int > [0, 1, 2], "3 Stroke Left, CW"); gesMan.register(new < int > [1, 2, 3], "3 Stroke Up, CW"); gesMan.register(new < int > [0, 3, 0, 3, 0],"Step Up"); gesMan.register(new < int > [0, 1, 0, 1, 0], "Step Down"); gesMan.register(new < int > [4], "South East"); gesMan.register(new < int > [5], "South West"); gesMan.register(new < int > [6], "North West"); gesMan.register(new < int > [7], "North East"); gesMan.register(new < int > [4, 5, 4, 5], "Zigzag"); stage.addEventListener(MouseEvent.MOUSE_DOWN, start); stage.addEventListener(MouseEvent.MOUSE_UP, end); }Step 18: Handling Results
Recording of gesture sequence follows the same approach as
CheckOut2. I assume readers have gone through Step 10. So finally, we shall output the result. Upon successful match (> -1), we shall scroll to the appropriate frame. Again, this is subject to whether you have enabled the use of sequence by turning onseqor not.private function end(e:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_MOVE, check); //evaluate gesture and output result var output:Array = gesMan.end() if (output[0] > -1) { if (seq)a.nextFrame(); else a.gotoAndStop(output[0] + 2); //offset needed as first frame is empty. } }Step 19: Publish Your Project
Press Ctrl + Enter to publish your project. Gesture with your mouse and what was detected. I’ve included both projects (one requests you to match a given gesture; the other displays the gesture you drew, if it matches one it knows). Have fun.
Step 20: Application Development
Inaccuracies in user gestures are common, and any application that incorporates gestures should consider this. In the next part of this tutorial, I shall attempt to use
MGestureandGManagerto develop an alphabet recognition application. I shall point out several details to tweak accordingly to improve gesture detection.Conclusion
You should now find it easy to develop applications that detect gesture sequences of any combination. Hope this tutorial has helped you in some ways. Let me know of your comments, queries and bugs encountered. Terima kasih.
A couple of months ago, Carlos showed Premium members how to create a Whack-a-Mole game using Flash and AS3. Now, following on from Monday’s introduction to EaselJS, he’ll explain how to use that library to create the same game with the HTML5 canvas and JavaScript.
Preview
Let’s take a look at the final result we will be working towards:
Click to try it out!
You can read the first five steps of the tutorial over on Tuts+ Premium, or join Premium to read the whole thing.
Active Premium Membership
We run a Premium membership system which periodically gives members access to extra tutorials, like this one! You’ll also get access to Psd Premium, Vector Premium, Audio Premium, Net Premium, Ae Premium, Cg Premium, Photo Premium, and the new Mobile Premium too. If you’re a Premium member, you can log in and download the tutorial. If you’re not a member, you can of course join today!
Also, don’t forget to follow @envatoactive on twitter and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.
In this series finale I’m excited to introduce you to the features that make TimelineMax so special. I’m also going to touch on some special tricks you can do with TimelineLite so that you can apply wild ease effects to the total play back speed of a timeline that includes hundreds of tweens and nested timelines. You have to see it to believe it.
TimelineMax in Action
The swf below contains a single TimelineMax with a repeat value of 1 and yoyo of true. The
totalTimeandtotalProgressvalues reflect the amount of time it takes for the entire sequence to run twice. TimelineMax’saddCallback()method is used to call a function that handles swapping the depths of the blob and the bush so that the blob can jump behind the bush. This swapping happens instantly when the blob finishes his upward movement regardless of whether or not the timeline is playing backwards or forwards.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!
TimelineMax Special Properties
TimelineMax’s most popular feature is that you can easily tell it how many times to repeat. There are a number of special properties that can be passed into the TimelineMax constructor’s
varsobject that help you fine tune exactly how the repeat works:tl = new TimelineMax( {repeat: 2, repeatDelay: 1, onRepeat: doSomethingCool, yoyo: true } );The code above will create a timeline that does the following:
doSomethingCool()will fire and the timeline will play backwards instantaneously.doSomethingCool()will fire and the timeline will play forwards instantaneously.Duration, Time and Progress
Once a timeline is told to repeat it is helpful to be able to access a number of properties that take into consideration the duration of all the iterations and delays:
It’s worthwhile to note that TimelineLite does have
totalDurationandtotalTimeproperties but since TimelineLite doesn’t repeat, they offer the most value when used with TimelineMax.Calling a Function From TimelineMax
TimelineMax makes it easy to call functions from any point in time. You may be familiar with the process of adding an
onComplete()callback to an individual tween in a timeline, butaddCallback()offers two advantages:addCallback()functions will be fired when the timeline is playing forwards AND in reverse.addCallback()doesn’t need to be locked to a particular tween endingaddCallback() Method signature:
tl = new TimelineMax(); tl.append( TweenLite.to( mc, 5, {x:500} ) ); tl.addCallback ( doSomethingCool, tl.duration-1, ["Steve"]) ); function doSomethingCool(someValue:String):void{ trace("Hi " + someValue); }The code above will cause the phrase “Hi Steve” to appear in the output panel one second before the previous tween ends.
Calling a Function From TimelineLite
TimelineLite offers similar functionality by way of appending or inserting a TweenLite.delayedCall() method but the code is a bit more verbose.
someTimelineLite.append( TweenLite.to( mc, 5, {x:500} ) ); someTimelineLite.append( TweenLite.delayedCall( 0, doSomethingCool, ["Steve"] ), -1 );Tweening the Playback of a Timeline
One of the best kept secrets of the GreenSock Tweening Platform is that you can tween a TweenLite, TweenMax, TimelineLite and TimelineMax. In the video I focus on tweening the playback of the “timeline brothers”. The benefit of tweening a tween or timeline is that you can adjust the speed at which it plays back and also apply easing.
Tween the timeScale of a TimelineLite/Max
This method is great for getting an animation to slowly come to stop at any point in time or resume playing with a nice ease-in. Notice the nice ease that is applied when entering or leaving a paused state.
Combine TimelineMax’s tweenTo() With an Ease
This method works well for applying an ease to the playback speed of an entire timeline or just a segment. Notice the radical change in playback of the timeline when the Circ In Out and Bounce Out buttons are pressed.
Hopefully the SWF above will entice you find out more by watching the video and downloading the source files.
Conclusion
There are more things that TimelineMax can do but I chose to focus on the most commonly used features. I gave you a look at TimelineMax’s
currentLabelproperty andgetLabelAfter()method in Part 4: Working with Labels. As always I recommend reading and bookmarking the TimelineMax documentation to be sure you are getting the most out the tools you choose to use. I still learn something new every time I poke around in there.It has been an amazing experience for me to share with you nearly three hours of TimelineLite/Max training. I am confident that if you take the time to watch through each video and experiment with the source files you will have an incredibly strong foundation to start building upon. The potential for what you can achieve with TimelineLite/Max is virtually limitless. I truly hope you are as excited as I am about what can be done with these amazing tools.
For those of you who want to continue your TimelineLite/Max education I am sure you will find the following tutorials very useful:
I have to give special thanks to Jack Doyle of GreenSock for creating these amazing tools and also offering his support throughout the creation of these videos. Never in my life have I come across a business or product creator that goes to the lengths that Jack does to keep his customers and legions of enthusiasts so darn happy.
Thanks so much for watching this series and providing feedback. If you would like to contact me with any questions related to TimelineLite/Max please comment below or send an email. You can find my email address at the end of the video.
-Carl
Stumped for what to put on your Christmas list? Or perhaps you’re out of ideas for what to get that special web developer in your life? Let us help! This bumper roundup of gift ideas is two lists in one: the first half is to help developers figure out what to ask for, and the second is to help their friends figure out what to get them!
Serious Business
Being at the end of the year, Christmas is a great time to prepare for the future. The first half of this list is aimed at web developers that are making a list for Santa or their friends and family; if you’re buying a present for another web developer, skip to the Just For Fun section!
General Web Development
JavaScript: The Good Parts
No, I’m not jumping on the “Flash is dead” bandwagon. But there’s no use denying that JavaScript is a very important language for any web developer today, and will become even more so over 2012. If you’ve been holding back from learning it, take a look at this book; it’s a great and highly-respected overview that might change your mind.
Also check out JavaScript Patterns – it’ll help you see how to make JavaScript less messy and more organised. Even AS3 developers could learn a lot from this.
Buy JavaScript: The Good Parts on Amazon
Essential ActionScript 3.0
If you want to stay relevant as a Flash developer, you’ll need to have very sharp AS3 skills. Colin Moock’s excellent book will fill in any gaps in your knowledge, covering everything in “classic” AS3 (meaning there’s nothing on Stage3D and the other newer features).
Warning: This book is not for beginners!
Buy Essential ActionScript 3.0 on Amazon
Head First C#
C# is a flexible language; it’s directly relevant to us because it can be used to develop Unity games and Silverlight apps, but it can also be used to make server-side apps (through ASP.NET), mobile and desktop apps (using Visual Studio), and Xbox 360 games (with XNA). From my own experiences, it’s also a fun language to use, and has a lot in common with AS3. If you’re looking to experiment with something new, it’s a great choice.
Head First C# is a great guide to get you up and running with the language as fast as possible; however, if you’re an experienced programmer already, you may find it a little slow-going. In that case, check out C# in Depth, as well.
Buy Head First C# on Amazon
Head First Design Patterns
If you work with any class-based OOP languages (AS3, C#, etc.) you must read this book. The only exception is anyone that read, absorbed, and fully understood the original GoF book.
Head First Design Patterns is the book that let me understand when the heck we’d ever use an
Interface. It takes the theoretical elements of OOP (inheritance, polymorphism, and all those other definitions from Wikipedia) and makes them practical. And it does that in the brain-friendly way that’s typical of the Head First series, so you’ll actually understand it.Buy Head First Design Patterns on Amazon
Adobe Web Premium CS5.5
I’ll admit: this is expensive. If you’ve managed without Web Premium so far, you’ll probably continue to manage just fine – though that’s not to say this isn’t useful. I own Web Premium CS5 and get a lot of value out of it (particularly Photoshop, Illustrator, and Flash Pro).
If you’re currently using CS4, I recommend upgrading – not because CS5.5 is so much better, but because when CS6 comes out in a few months, you won’t be eligible for upgrade pricing otherwise. See this article on Psdtuts+ for more info.
Buy Adobe Web Premium CS5.5 on Amazon
WebStorm (HTML/CSS/JavaScript IDE)
Sure, you can write HTML, JavaScript, and CSS in a plain text editor like Notepad++ or TextMate, but a decent IDE makes the task so much easier, so much less tedious, and so much less prone to silly typos.
WebStorm is great for browser-based apps and games; check out Jeffrey Way’s thoughts over at Nettuts+ for more info.
Buy WebStorm from JetBrains
App Development
Head First HTML5 Programming
If you’re a little confused about what HTML5 actually is (besides a buzzword, apparently), and you’re only familiar with HTML…4, then this book will clear everything up while teaching you how to develop HTML5 apps along the way.
As with many Head First books, it’s great for beginners but perhaps a little slow for experienced developers. If you’re already very familiar with AS3 and JavaScript, consider HTML5 Up and Running (also available for free online as Dive Into HTML5), which covers what’s new in HTML5 from that perspective.
Buy Head First HTML5 Programming on Amazon
Design for Hackers
Programmers do not have a reputation for being good at design. This book aims to remedy that, by teaching the basic principles of design as they apply to web apps and mobile apps, in a way that can be understood by hackers.
Another excellent book on the topic is the Non-Designer’s Design Book, although that focuses on print and static web design, rather than interactive apps.
Buy Design for Hackers on Amazon
Head First jQuery
jQuery is an incredibly popular JavaScript library – view the source of the next few web pages you visit, and see whether they use it. It’s designed to make coding JavaScript web applications easier, by simplifying how you access the DOM, use events, and create animations. (My simple description here does not do it justice.)
I would have picked jQuery: Novice to Ninja for this roundup, and that’s still a great choice – but I suspect you’d be better off waiting for the new edition of that book, which is due on February 22, and reading Head First jQuery in the meantime.
Buy Head First jQuery on Amazon
Guide to Robotlegs
Robotlegs is to AS3 as jQuery is to JavaScript – not in terms of its scope, exactly, but rather in that it’s an AS3 framework that makes developing web apps much simpler and more manageable. This book, by Stray and Joel Hooks, explains how to use Robotlegs to develop two example apps, simultaneously teaching good app architecture and Robotlegs itself. Check out Stray’s post for more details.
Buy Guide to Robotlegs on Amazon
Game Development
Unity Game Development Essentials
This is the definitive book for Unity beginners. Throughout the book, you’ll build a single 3D game, adding new features and learning about new aspects of Unity in each chapter.
Check out our interview with Will Goldstone, the author.
Buy Unity Game Development Essentials on Amazon
Unity Game Development by Example
This is the other definitive book for Unity beginners. It takes a different approach to Will Goldstone’s; Ryan’s writing style is very different (you’ll know what I mean if you’ve read his blog), and he builds up a selection of games in both 2D and 3D, rather than focusing on one big project. If you’re new to Unity, get both!
Check out our interview with Ryan Henson Creighton, the author.
Buy Unity Game Development by Example on Amazon
Making Things Move!
The full titles of this book is Foundation ActionScript Animation 3.0: Making Things Move! – but don’t be fooled, this isn’t about hand-drawn, frame-by-frame animation or tweens. This is about making things move through code: billiard ball physics, kinematics, collision detection, momentum, gravity, and other such topics are covered, as well as the relevant areas of maths and physics that you might not remember from school.
There are plenty of books about Flash Game Development, but in my opinion this is the first one you should read – at least if you’re making a platformer, a shoot-’em-up, a breakout clone, or anything else involving motion. For card games, strategy games, hidden object games and the like, you might want to look elsewhere.
Buy Making Things Move! on Amazon
Flash Stage3D Game Programming
HTML5 may be catching up to Flash in certain areas, but the Flash Platform isn’t standing still. The most impressive new feature of Flash Player 11 is Stage3D, which adds awesome 3D rendering capabilities to the Player. Like Will Goldstone’s Unity book, this will take you through the process of building a 3D game from start to finish, adding more each chapter.
Check out the author’s page for a look at the final game!
Buy Flash Stage3D Game Programming on Amazon
The Art of Game Design
This book takes a look at game design in general terms, without being tied down to a specific platform – indeed, one section of the book recommends building some physical board games or card games, to get to the heart of what makes game mechanics work.
I can’t praise this book highly enough. It’s fascinating and fun to read, as well as being packed with practical information. By the end of it, you’ll be able to say, “I am a game designer.”
Buy The Art of Game Design on Amazon
A Theory of Fun
Another excellent book on game design that’s not tied down to a platform. This book centers around one concept – that the fun in games comes from the player attempting to fully understand a pattern – and explores it in depth, with a ton of examples and illustrations.
Take a look at the early comic form of the book to see whether it’s the sort of thing you’d enjoy.
Buy A Theory of Fun on Amazon
Subscriptions
Tuts+ Premium
I’d be remiss if I didn’t mention Tuts+ Premium. The amount of material available on the site today is staggering: ebooks, full courses, and of course all the tutorials. Check out my earlier post for the reasons why I recommend signing up. You can buy a year’s subscription at a 20% discount compared to paying monthly.
Sign Up to Tuts+ Premium
Safari Books Online
I’ve written a full review of Safari Books Online on my own blog; in summary, it’s the Netflix of technical books. Almost every book listed in this roundup is available for you to view in your browser, meaning you can read them on your computer, your tablet, or your phone.
There are different payment plans: the cheapest lets you read up to five different books a month, while the most expensive lets you read as many as you like, and gives you full text search across the contents of the entire catalog.
Sign Up to Safari Books Online
Dropbox
Dropbox takes a section of your hard drive and shares it across all your devices, so you can access your files on any computer or smartphone and via their web app. What’s really impressive is how it remains so invisible: it just sits in the background and syncs everything, without you having to think about it or do anything.
The only problem with the free version is that it’s limited to just 2GB of space. A subscription can bump that up to 50GB or 100GB, and also allow you to access previous versions of files, and files that were deleted, via the Pack-Rat add-on.
Get a Dropbox Pro Account
Evernote
I love Evernote. Like Dropbox, it syncs things across different devices, but unlike Dropbox, it’s focused specifically on notes rather than general files. At its core, it gives you an interface for typing in bits of text, and letting you search across all of them later. But there are plenty more bells and whistles, like tagging, the ability to extract text from images, rich text editing, and so much more. I don’t use bookmarks any more: I use the browser extension to clip the most interesting parts of the page, and tag it so that I can find it later.
The Premium program gives you more space, lets you view previous revisions of notes, and gives you the ability to share notes with other people, as well as some other enhancements.
Go Premium with Evernote
Just For Fun
Okay, that covers stuff that developers need. Now, how about stuff they’ll want? If you’re a developer reading this, maybe you should send the article to your family and friends, and stop reading here so that you don’t spoil the surprise…
Hobbies
Cooking for Geeks
Cooking is great fun; it’s creative, and at the end of it, you have something delicious to eat. This book makes cooking accessible to geeks that don’t know their way around the kitchen yet, but contains plenty of inspiration for those that have been cooking for years.
It also contains plenty of ideas for cookware and gadgets to buy for those that love to cook.
Buy Cooking for Geeks on Amazon
Arduino
Arduino is like LEGO Mindstorms for grown-ups. In brief, it makes it much easier to design and build electronics. This means it can take programming away from computers, and into the physical world.
The start kit suggested here is just one of many that are available; check out the Arduino homepage and search Google for others. There are plenty available to fit different budgets and interests.
Buy the Adafruit Arduino Experimentation Kit
The Best of Instructables
Instructables is a website for Do-It-Yourself projects that aren’t just about putting shelves up. Food, furniture, toys, and costumes are covered here, so there’s plenty of inspiration for someone wishing to get hands-on with their creativity.
Buy The Best of Instructables on Amazon
Geocaching Phone Starter Kit
Geocaching is modern day treasure hunting. Over a million “caches” are hidden across the world, and geocachers use the website and a GPS device to find them, logging their name when they do.
Most web developers will already have a phone with GPS, which is enough to play the game, so this kit just adds a bit more fun to the hunt (as well as making it easier to participate in bad weather).
Buy Geocaching Phone Starter Kit from Geocaching.com
If you’re buying a gift for a photographer (hobbyist or professional), check out The Official 2011 Phototuts+ Holiday Gift Guide on our sister site Phototuts+. For illustrators and designers, Vectortuts+ has a great gift guide too.
Leisure
Skyward Sword
A lot of amazing games came out in the last couple of months, let alone the last year: Skyrim, Arkham City, Uncharted 3, Battlefield 3, Assassin’s Creed 3, and many more. Rather than turning this into a “best games of 2011″ roundup, I’ll mention my two personal favourites. The first is the latest Zelda game, Skyward Sword.
This is an RPG without the grind; it’s part adventure and part puzzle. The controls make full use of the WiiMotion Plus (so it requires the right attachment or controller): as well as letting you aim and pilot by pointing and tilting the Wiimote, it also moves Link’s sword to follow the Wiimote, leading to some great puzzles. I can’t do it justice in this small space; read Edge’s review for more details.
Buy Skyward Sword on Amazon
Sonic Generations
Sonic Generations complements Skyward Sword nicely: Skyward Sword is only on Wii, while Sonic Generations is on every platform but Wii; Skyward Sword is best enjoyed in chunks of an hour or two at a time, while Sonic Generations is still fun in ten-minute doses; Skyward Sword requires a lot of thinking, backtracking, and solving puzzles, while Sonic Generations is fast-paced, almost like an arcade racing game.
Sonic Team has put out some real stinkers over the past decade, but Sonic Generations finally gets it right. It features revamped levels from previous games – Chemical Plant in full 3D! – so there’s a great nostalgia kick to it as well.
Buy Sonic Generations on Amazon
In the Plex
Again, with so many non-tech books released in a year, it’s impossible to write a comprehensive roundup, so I’ve just picked my favourite.
In the Plex is essentially Google’s biography, from the founders’ days at Stanford, through their hiring of a CEO, past the invention of Gmail and the troubles in China, up to the present day with the launch of Google+. It’s a fascinating story for anyone that’s interested in the web.
Buy In the Plex on Amazon
The Complete Calvin and Hobbes
I’ve never met anyone that dislikes Calvin and Hobbes, but geeks seem even more aware of it and fond of it than the general public. This collection contains almost every single comic (in glossy full colour where appropriate), with an introduction and commentary by Bill Watterson.
For someone that’s new to the pair, The Essential Calvin and Hobbes would be a better (and cheaper, and easier to read) introduction, but for a long-time fan, the Complete box set is a wonderful thing to own.
Buy The Complete Calvin and Hobbes on Amazon
Go the F–k to Sleep
This is a book for parents with young children and a sense of humour. As you can probably guess by the title, it’s a children’s bedtime story with a lot of profanity. Even better: the audiobook version is narrated by Samuel L. Jackson.
Buy Go the F–k to Sleep on Amazon
Community
The Wire, Breaking Bad, Misfits, Game of Thrones… again, plenty of great TV box sets to choose from. So why Community? Because it’s consistently smart and funny. The first two series are some of the best TV I’ve ever seen.
Buy Community Series 1 and Series 2 on Amazon
Accessories
Amazon Kindle (E-Ink)
With all the books recommended above, perhaps it’s time to go digital. I’ve had a Kindle 3 for just over a year now, and I love it. It doesn’t sound like an amazing invention – “it’s basically a cut-down tablet, right?” – but anyone that enjoys reading would benefit from owning one.
There’s no hassle in it being electronic: the display uses actual ink that’s rearranged electronically, which makes it sharp and clear (and not like staring at a lightbulb), and even with daily reading, it can last a few weeks without needing to be recharged. But it reduces some of the hassle you probably don’t even notice is in a book: any book you order is delivered in seconds; no matter how many books you own, it doesn’t take up any more space in your bag; you can look up the meaning of any word with a few key presses, and you can highlight passages and keep notes on them that get synced to the internet.
The model shown here is a Kindle Touch, though there are others available, with different designs and at different price points.
Buy Amazon Kindle on Amazon
Tablet
Some tech sites speculate that tablets are going to cut in to PC sales, with more and more people buying a new tablet instead of a new laptop. I don’t think this is going to be the case for web developers, so a tablet still remains a luxury as far as I’m concerned – although one could justify such a purchase to the tax man, since it’s handy for cross-browser testing.
The iPad 2 is still the device to beat here, but some very nice Android alternatives are popping up: there’s the Transformer Prime, with optional keyboard dock that turns it into a netbook, and the Samsung Galaxy Tab’s 8.9″ and 10.1″ models. For those on a budget, the Kindle Fire is probably the best, although reviews have expressed disappointment.
iPad 2, Kindle Fire, Transformer Prime, Galaxy Tab
Messenger Bag
For years I carried my computer in a cheap old laptop bag that looked awful and hurt my shoulder. Splashing out on a decent bag felt like overspending on a luxury, and the amount of choice was paralysing. I’m very glad I got past that to buy a Timbuk2 D-Lux (pictured), because now I take it everywhere. It carries my shopping, it has a Napoleon pocket for my Kindle, it’s my in-flight bag when I go on aeroplanes… I love it.
Like I say, there’s a lot of choice available – take a look at Rands’s excellent post on choosing a bag to see what I mean – but this might make it a perfect gift.
Buy a Timbuk2 D-Lux (pictured)
Charity
Kiva
I’m not going to prioritise one cause over any other, but as a gift, a Kiva card makes a lot of sense, because the recipient gets to make a personal choice over what to donate it to.
Actually, “donate” isn’t quite the right word; Kiva works through micro-loans. A Kiva user might lend $25 to a third-world school that needs to buy books, or a market seller who needs to buy his initial stock, or a farmer that needs to buy new livestock. Over time, these entrepreneurs make the money back, and repay the loan – which can then be lent to another worthy cause. This means it’s literally a gift that keeps on giving.
Buy a Kiva gift card
I hope that’s helped inspire you this Christmas! Don’t forget to check out the other Tuts+ sites for their gift guides over the next few days.
If you’ve got any other gift ideas, please share them in the comments!
There’s been some resistance from Flash developers to our new HTML5 content. In this article – aimed at experienced AS3 coders – we’ll look at EaselJS, a JavaScript library that makes working with the HTML5 canvas very similar to working with the Flash display list.
The HTML5 Scene
The “war” between Flash and HTML5 isn’t news to anyone involved in browser or mobile development and as Michael points out there’s no harm in learning HTML5 even if you know Flash and ActionScript.
HTML5 is a new and evolving technology and there are currently no full-featured tools quite like the Flash IDE covering the whole workflow to create games or applications, but if you’re familiar with Flash Builder or FlashDevelop it shouldn’t be hard to code in any text editor using external files as your assets.
(Editor’s Note: There are plenty of JavaScript and HTML editors, though – take a look at JetBrains WebStorm for a great example.)
Introducing EaselJS, Tween JS and SoundJS
Luckily for us, Grant Skinner has developed a JavaScript library that will make our learning less complicated. In his own words:
EaselJS uses a similar syntax to ActionScript; it has a Display List, Stage, Graphics and even Filters, this will make working with the canvas easier for us Flash developers.
Additionally we can complete our easel development with the TweenJS and SoundJS scripts which, as the names suggest, handle animations and sound.
The Display List
The Display List works very similar to ActionScript:
In this code, the
myStagevariable is the linked reference of the canvas to the Stage class in EaselJS. More on that in the example at the end of this tutorial.Mouse Events
The way to add Mouse Events couldn’t be easier:
myChild.onPress = myFunction myFunction(){console.log('pressed');}Text
This code adds a Text object and places it in the stage.
var myText = new Text('Activetuts+', 'Bold 15px Helvetica', #FFF); myText.x = 25; myText.y = 25; myStage.addChild(myText); myStage.update();Tickers
The Ticker class provides a centralized tick or heartbeat, broadcast at a set interval; the
tick()event can be used as a substitute for an AS3 Timer or EnterFrame event.The following code sets the frame rate to 30 and deines the stage as the listener for the ticks.
Tweens
The Tween class is an external addition to EaselJS which is available by adding the TweenJS script to our document. It works very similarly to tween engines in ActionScript.
Sounds
We can play a sound by adding the SoundJS script to our document and writing the following code:
SoundJS.add('mySound', 'mySound.mp3', 1); SoundJS.play('mySound');Hello World!
An introduction to a programming library would not be complete without a hello world example! Follow these steps to create a very simple HTML5 Canvas hello world containing images, mouse events, text and more.
Step 1: HTML Structure
Let’s prepare our HTML document, it is a simple html structure to begin writing our app.
Step 2: Hide Mobile Highlight
Let’s add a little bit of CSS too: this line will remove the default highlight when you tap on an element using a mobile browser; without this the mobile experience would decrease drastically.
<!DOCTYPE html> <html> <head> <title>Hello World</title> <style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> </head> <body> </body> </html>Step 3: JavaScript Libraries
The following code adds the necessary JavaScript libraries for our app to work.
<!DOCTYPE html> <html> <head> <title>Hello World</title> <style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> <script src="easel.js"></script> <script src="Tween.js"></script> <script src="HelloWorld.js"></script> </head> <body> </body> </html>Step 4: Call Main Function
In the next lines we call our constructor, this is the main function that will be created later in our javascript code.
<!DOCTYPE html> <html> <head> <title>Hello World</title> <style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> <script src="easel.js"></script> <script src="Tween.js"></script> <script src="HelloWorld.js"></script> </head> <body onload="Main();"> </body> </html>Step 5: Canvas Tag
The Canvas is added in this line, we assign an ID to reference it later and also set its width and height.
<!DOCTYPE html> <html> <head> <title>Hello World</title> <style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> <script src="easel.js"></script> <script src="Tween.js"></script> <script src="HelloWorld.js"></script> </head> <body onload="Main();"> <canvas id="HelloWorld" width="480" height="320"></canvas> </body> </html>Step 6: JavaScript
Let’s begin our app creation!
Open your preferred JavaScript editor (a basic text editor will work, but you won’t have syntax highlighting) and prepare to write your awesome app. Remember to save the file with a js extension in your project folder.
Step 7: Define Canvas
We’ll start by defining all the graphic and logic variables.
The next variables represent the HTML canvas element and the stage that will be linked to it. The stage variable will behave in a similar way to the AS3 stage.
Step 8: Background
This variable stores the background image.
Step 9: Button
Another variable to store the button image.
Step 10: Variables
These are the variables we’ll use, read the comments in the code to know more about them:
Step 11: Constructor
The constructor is a function that runs when an object is created from a class; this particular function will be the first to execute when the web page is loaded.
function Main() { //code... }Step 12: Link Canvas
This code gets the HTML canvas ID and links it to the EaselJS Stage class. This will make the stage variable behave like the Stage class in AS3.
/* Link Canvas */ canvas = document.getElementById('HelloWorld'); stage = new Stage(canvas);Step 13: Enable Mouse Events
Mouse Events are disabled by default in EaselJS to improve performance. Since we need those in the application, we’ll add the following line:
Step 14: Load Graphics
This code is used to preload the graphics with the help of a function that we’ll write later. It sets the Image object we created before to the source png file in our document folder. A name is given to detect which image is loaded and lastly the function that handles the loaded images is called.
You’ll need to download the images from above (or make your own) in order for this to work.
Step 15: Set Ticker
The following code sets the frame rate to 30 and defines the stage as the listener for the ticks.
The TweenJS class will listen to this tick to perform the animations.
Step 16: Preload Graphics
Every time a graphic is loaded this function will run. It will assign each image to a bitmap object and check that all the elements are loaded before proceeding.
function loadGfx(e) { if(e.target.name = 'bg'){bg = new Bitmap(bgSrc);} if(e.target.name = 'button'){btn = new Bitmap(btnSrc);} gfxLoaded++; /* Display graphics until all of them are loaded */ if(gfxLoaded == 2) { buildInterface(); } }Step 17: Build Interface
This code places the graphics on the stage and adds a mouse listener to the button.
function buildInterface() { btn.x = centerX - 40; btn.y = centerY - 12; stage.addChild(bg, btn); stage.update(); // Very Important /* Add button listener */ btn.onPress = showText; }Step 18: Show Text
The function that will run when the button is pressed, explained in the code commentary.
function showText() { console.log('This works like trace!'); /* Remove Listener */ btn.onPress = null; /* Create Text */ var msg = new Text('Hello World!', 'Bold 25px Arial', '#EEE'); msg.x = centerX - 70; msg.y = centerY; stage.addChild(msg); msg.alpha = 0; /* Animation */ Tween.get(btn).to({y:centerY + 50}, 300); Tween.get(msg).wait(400).to({alpha:1}, 400); }That’s it! Click here to see this simple demo in action.
Conclusion
Congratulations! You just made an HTML5 canvas application compatible with all major browsers, including mobile. Stay tuned for more here on Activetuts+.
I hope you liked this tutorial, thank you for reading!
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:
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,:
Select the whole stage, right-click and choose Convert to Symbol. Name the MovieClip
goldSlideand 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
goldSlideMovieClip 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 toblueSlide,greenSlideandredSlide.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
sideButtonMovieClip 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:
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.
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.
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:
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:
Your stage should now look like this:
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 asMenuSlidesMC.Before we finish we must give each of the MovieClips inside
menuSlidesMCan instance name. Select each slide in the order they appear from the left and name themslide1,slide2,slide3andslide4respectively. Name the circle buttonsone,two,threeandfour, and finally name the side buttonsleftandright.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 asmenuSlides.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
menuSlidesMCinstance. Save it asMenuSlidesMC.asand 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 ofactiveSlide, 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 ofactiveSlidethey set it to the selected value.Now let’s begin with the
ENTER_FRAMEhandler function:public function slidesMove(event:Event):void { }Add the
slidesMove()function below yourslidesClick()function and we’ll start adding some code to it. First, we’ll use aswitchto check which slide should be on the screen, based on the value ofactiveSlide: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.
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.
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
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
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
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
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
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
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
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
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
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
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)*speedStep 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!
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()andinsertMultiple()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):Arraytweens: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 useTweenMax.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 thetweensparameter in theappendMultiple(). If you were to useallFrom()in anappend()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.NORMALandTweenAlign.STARTTweenAlign.NORMALandTweenAlign.STARTNotice how the delay is ignored with
TweenAlign.STARTTest 2: See how the stagger works differently depending on align mode
Notice how stagger works differently with TweenAlign.NORMAL and TweenAlign.START:
TweenAlign.NORMAL, stagger is the amount of time between the start of each tween.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 withinsertMultiple()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()andinsertMultiple()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!
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:
Other posts help readers discover useful and inspirational content that’s relevant to their niche:
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!