Migrating Studio Roosegaarde from Flash 8 with ActionScript 2.0 to Flash 9 with ActionScript 3.0

I’m currently moving a website from Flash 8 to Flash 9. The migration is working quit well for me, but it’s no trivial thing to do.

The start is easy; just open up your *.fla file in Flash 9, no trouble there. (I only had to re-embedded my fonts to the library to have them properly attached to the published SWF.) The fun starts once you’ve set your export/publish settings to Flash 9 with ActionScript 3.0 and try to compile the Flash movie.

Publish Settings Dialog

Adobe has a list of things that changed between ActionScript 2.0 and ActionScript 3.0, that was a good starting point for me. But I think there’s a lot that’s yet undocumented. At least there where some things that I did not find documented at the time I needed them. This blog post sums up some of the problems (and my solutions to them) that I encountered.

I tried to structure this a bit but as there’s a lot off overlap between the subjects I utterly failed. :)

MovieClips

Where MovieClip used to be the mostly likely candidate base class of all your custom “displayable” classes, DisplayObject now takes this role. MovieClip is derived from this class, but there’s also Sprite and Shape (which don’t suffer the overhead that comes from having a timeline).

The MovieClip (flash.display.MovieClip) properties that you used to modify most often (_x, _y, _xscale, _yscale, _alpha, _rotation, _xmouse, _ymouse) are still there but are now derived from DisplayObject (flash.display.DisplayObject) and they’re named slightly different.

  • _x = x
  • _y = y
  • _xscale = scaleX
  • _yscale = scaleY
  • _alpha = alpha
  • _rotation = rotation
  • _xmouse = mouseX
  • _ymouse = mouseY

[0,100] is now [0,1]

Another important thing to not about these is that the scale, alpha an rotation values used to be in the range [0,100] but are now in the range [0,1]! Which off course means that you should divide your values for them by one hundred to obtain your desired result in Flash 9. I think this [0,100] to [0,1] range issue goes for all the properties that used to have a zero to hundred range. (I did for example encounter it when working with the sound volume of MP3s.)

There’s no _root

There’s no globally accessible reference (_root) to the stage timeline. DisplayObjects property root references the root of the movies display tree given that the DisplayObject is attached to that tree!

The new Display Tree

All DisplayObjects can be ordered in a display tree. You can choose which class will initiate an object to be the root of this tree (any Class extending a DisplayObject will do) in the Stage’s properties dialog.

Stage properties dialog

This DisplayObject and any runtime childs of it will be displayed in your SWF movie. Filling your display tree is done by calls to addChild or addChildAt. Removing childs by calls to removeChild or removeChildAt. Reordering (in the sense of vertical stacking) is done with swapChildren and swapChildrenAt.

Vertical ordering

Here’s a major difference between ActionScript 2.0 and ActionScript 3.0. There’s no longer a depth property! The stacking order of MovieClips is no determined by how they are ordered in the Childs list of there parent. First child at the bottom of the stack and higher numbers higher upon the vertical stack.

This presented me with a serieus problem. Check out the following image.Daan Scroller

This is what I call “the scroller” in Studio Roosegaarde, it’s a giant Rolodex that comes in a variety of forms and behaviors to entertain the visitor. The scroller is 3D although there’s no real 3D support in ActionScript 2.0. The scroller comes in ellipse forms and by defining that the spot at which the picture is the closest to the viewer is at angle 0, all pictures have a unique angle. In ActionScript 2.0 I had implemented the right vertical stacking order by a function that mapped the angles to depths. But this will no longer work. I can’t use the depth property any longer and even the values that I calculated are of no use anymore. I can’t use them as the indexes for the Child list since the numbers are not necessarily consecutive ones. (They may leave giant gaps in the childs list).

Here’s the elegant solution that I found. Instead of using the angle property I’m now using the would-be z value (if Flash was 3D) of the movieclips to map them to an index in the parents child list.

//arrange display objects in child stack

sortedDisplayObjects.sortOn(“z”, Array.NUMERIC | Array.DESCENDING);

var numDisplayObjects:int = sortedDisplayObjects.length;

for(var j:Number = 0; j < numDisplayObjects; j++)

if (getChildAt(j) != sortedDisplayObjects[j])

setChildIndex(sortedDisplayObjects[j], j);

The sortedDisplayObjects is an array that I filled with DisplayObjects that I want to be vertically ordered. All of those objects I gave an publicly accessible property named z. Every time some z value changes this code reorders the DisplayObjects. (In my implementation the reordering is done in every frame, since the Rolodex is constantly moving.)

The new event model!

The new event model is a serious blessing. It’s consistent over all sorts of events and it is implemented in a way that the scope issues that required you to use Delegates in ActionScript 2.0 are eliminated. And I think Adobe recognizes that it’s done a good job with this, ’cause they have written good documentation on their new event model.

No more asfunction

It’s no longer possible to use the global function asfunction in your HTML anchors to let hyperlink clicks result in some actionscript function executing. Everything is now done using the same event-mechanism, and so you need to give your HTML text fields an event listener that listens for TextEvent.LINK event.

Here’s an example. My HTML anchor used to have the following form;

<a href=”asfunction:somefunctionname,an_optional_parameter”>some text</a>

This won’t work anymore. By using a simple regular expression I’ve replaced all occurencies of the old asfunction with event, the new way of triggering the link event.

//replace “asfunction” with new “event”
var
pattern:RegExp = /asfunction/gi;
blog_text = blog_text.replace(pattern, “event”);

No all you have to do is listen for the event

blog_entry_txt.addEventListener(TextEvent.LINK, (root as StudioRoosegaardeRoot).linkEvent);

and couple it to the right action.

public function linkEvent(event:TextEvent):void {
var the_link_clicked:String = event.text;
var link_parts:Array = the_link_clicked.split(“,”);
//do something
}

XML Parser

The XML parser works like charm. This used to be so and luckily still is.
There is however one thing missing that I really need and that’s a getElementsByTagName function.
Therefore I still have a XMLToolkit class with one static function getElementsByTagName.
I have that function described in this post but borrowed it from this one. :)

One thing that I noticed and that might help someone reading this is that you should set ignoreWhite property of a XMLDocument at the right time. (ignoreWhite prevents white characters between your xml elements from being parsed as XMLNodes, this is really usefull if you, like me, generate your XML’s not in one giant line of characters but in a more human readable layout.)
Let’s say you had an URLLoader yourXMLLoader load your XML and in handling the Event.COMPLETE event you try to parse the XML like this;

var yourXML:XMLDocument = new XMLDocument(yourXMLLoader .data);
yourXML.ignoreWhite = true;

Sadly this won’t work the way you suspected, luckily this will;

var yourXML:XMLDocument = new XMLDocument();
yourXML.ignoreWhite = true;
yourXML.parseXML(
yourXMLLoader .data);

I guess the reason for this behavior lies in the fact that the default ignoreWhite value is false and the XMLDocument constructor that receives an argument will be so proactive to immediately parse it. (As oppossed to a lazy approach in which it would parse it’s document when needed.)

String functions – No more need for your own String Toolkit

If you’ve read my blog posts about Flash 8 with ActionScript 2.0 you’ve noticed that I’ve encountered lot’s of missing functionality there. My biggest irritation was the absolute lack of any direct String functionality. Not even for the most trivial tasks. This has changed! Check out the String datatype and it’s new methods. The regular expressions make the string functionality complete.

Regular Expressions

Checkout the new regular expression functionality and see how powerful it is when combined with String.match(), String.replace() or String.search(). (For a general introduction to Regular Expressions read this.)

There’s still no String.trim() functionality. Here’s how I implemented it using RegExp.

function trim(value:String):String
{
var re:RegExp = /^([\s]*)([^\s].*[^\s])([\s]*)/s;
return value.replace( re, “$2″ );
}

Removing DisplayObjects

Removing DisplayObjects works by calling an DisplayObjectContainer’s removeChild function. I’m so excited about this! New Flash users might not see the significance of this, but you would appreciate this as much as I do I you knew what a hassle it occasionally was to remove MovieClips from the Stage in ActionScript 2.0.

My overall conclusion

My personal opinion is that Adobe took Flash and ActionScript a giant leap forward. The whole programming model is far more consistent and the performance of my project “feels” way better since I migrated it to the new technology.

Feel free to leave a comment if you encounter problems in migrating your project, chances are I encountered the same and have a solution!

10 Responses to “Migrating a Flash project from Flash 8 ActionScript 2.0 to Flash 9 (CS3) ActionScript 3.0”


  1. I just encountered an additional difference between ActionScript 2.0 and ActionScript 3.0
    This used to be a valid format for input to the LoadVariables class;
    &var1=value1&var2=value2
    With the URLVariables class in ActionScript 3.0 this is no longer valid input since the first ampersand must be omitted.
    So check for that ampersand in your migration code.
    Here’s example code that does that check;
    if(namevaluepairs.charAt(0) == “&”)
    namevaluepairs = namevaluepairs.substr(1,namevaluepairs.length-1);
    var result_lv:URLVariables = new URLVariables(namevaluepairs);

  2. daan Says:

    great work Theo!

    best,
    Daan


  3. When I try to retreive data from the TextEvent.text parameter (the last one mentioned below) I get the following COMPILER error:

    “1119: Access of possibly undefined property text through a reference with static type flash.events:Event.”

    Is this a bug??? All the other parameters come through fine, it’s just the “text” parameter that seems not to work.

    Here is what Adobe says about the TextEvent constructor:

    ————————————————-

    TextEvent () Constructor
    public function TextEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false, text:String = “”)

    Language version: ActionScript 3.0
    Player version: Flash Player 9

    Creates an Event object that contains information about text events. Event objects are passed as parameters to event listeners.

    Parameters

    type:
    String — The type of the event. Event listeners can access this information through the inherited type property. Possible values are: TextEvent.LINK and TextEvent.TEXT_INPUT.

    bubbles:
    Boolean (default = false) — Determines whether the Event object participates in the bubbling phase of the event flow. Event listeners can access this information through the inherited bubbles property.

    cancelable:
    Boolean (default = false) — Determines whether the Event object can be canceled. Event listeners can access this information through the inherited cancelable property.

    text:
    String (default = “”) — One or more characters of text entered by the user. Event listeners can access this information through the text property.

    ——————————————————————–

    Here’s how I’m testing this:

    1) create a new CS3 (AS3) FLA file.

    2) drop the “TextArea” component into the library (it will also copy in the UIScrollbar)

    3) copy and paste the following code into the first frame:

    ////////////////// BEGIN CODE ///////////////////////////////////

    import fl.controls.TextArea;

    var wordA = “Word A”;
    var DefA = “Word A definition.”;
    var myText:String = “Send TextEvent data to output screen“;
    var myTextArea:TextArea = new TextArea();
    myTextArea.htmlText = myText;
    myTextArea.setSize(500, 50);
    myTextArea.move(10, 10);
    addChild(myTextArea);

    var myTextAreaOutput:TextArea = new TextArea();
    myTextAreaOutput.setSize(500, 150);
    myTextAreaOutput.move(10, 100);
    addChild(myTextAreaOutput);

    myTextArea.addEventListener(TextEvent.LINK, showDef);

    function showDef(evt:Event):void{
    myTextAreaOutput.htmlText = evt.toString(); //Works!
    //myTextAreaOutput.htmlText = evt.bubbles.toString(); //Works!
    //myTextAreaOutput.htmlText = evt.type; //Works!
    //myTextAreaOutput.htmlText = evt.eventPhase.toString(); //Works!
    //myTextAreaOutput.htmlText = evt.cancelable.toString(); //Works!

    //myTextAreaOutput.htmlText = evt.text.toString(); // Does NOT work
    //myTextAreaOutput.htmlText = evt.text; // Does NOT work
    }
    //////////////////////////////// END CODE ////////////////////////////////////////////////////////

    I could probably do a work-around approach and extract the data I need from evt.toString(), but I’d really like to avoid doing that.

    Cheers,
    Mark


  4. @Mark Eberhart
    I think you have to just change your event listeners function signature and you’ll be fine. State explicitly that it handles a TextEvent. Like this;

    function showDef(evt:TextEvent):void

    (TextEvent is a subclass of Event. So Flash can cast from TextEvent to Event but not the other way around!)

    Good luck with it.

  5. charitha Says:

    Hello,

    I opened Flash 8 AS 2.0 project using Flash 9.0 but I didn’t get the “ActionScript 3.0″ item in the actionscript version field of the publish settings. It only has listed version 1.0 and 2.0. Any help is appreciated.

    Thanks


  6. Hi Charitha,

    have you tried saving the project as a Flash 9.0 first?

  7. Charitha Says:

    Hi,

    Thank you very much for the help. I resolved it. Keep up the good work.

  8. nikhil singh Says:

    hi Mark
    I have my console that crashes using FP9 but it works fine in FP7. Could you please tell me the possible ways why it is happening. Or should i migrate from AS2 to AS3.Kindly assist me with that.
    thanks and regards
    nikhil singh

  9. galori Says:

    Your trim regex is good but it misses strings that have only whitespace characters (such as ” “), here is my modification to fix that issue:

    private function trim(str:String):String {
    var re:RegExp = /^\s+|\s+$/sg
    return str.replace( re, “” );
    }


Leave a Reply