flashactionscript-3apache-flexmxmlcmtasc

Migrating to Flex mxmlc from ActionScript 2 mtasc


Years ago I created a tiny, simple SWF just to play MP3 files on various browsers. I exposed interfaces and called them from JavaScript. It was all small and straightforward; you can see the entire Guise.as source code.

I compiled the main class using mtasc, which allows you to specify a main function for initialization code:

/**Main entry point.*/
static function main(mc)
{

This was working just fine until I wanted to add WAV support. Flash doesn't natively support WAV, so I tried to add in a library. But the library required Flash 10 and wouldn't compile on mtasc, so I downloaded Flex 4.6 and tried to use mxmlc. Boy, was my pain only beginning.

My compiled SWF no longer works---even for MP3 files. I don't know where to start finding the problem, but I know I have lots of unanswered questions---maybe one of them is my problem:

Any feedback would be appreciated. I'm sure there's just one or two little adjustments that's throwing the whole thing off, but maybe with a little help from the community I won't have to spend several days reading entire books and buying new SDKs just to recompile my SWF with a couple of new calls... Thanks.


Solution

  • I don't think I can answer all of your question, but I'll try to provide some answers:

    ActionScript 3 is a substantial change from ActionScript 2. Its a complete architectural overhaul, not just a minor update and its not backwards compatible, so short of a re-write, its usually pretty difficult to tweak non-trivial as2 to compile as as3. It's pretty much like an entirely new language . So it might be best to take a step back and see whats changed in the language, because it's a lot.

    The biggest thing is the formalized class inheritance, over prototypical inheritance.

    So, when you compile from the command-line, you give it the path to the "main class":

    mxmlc.exe "c:\dev\project\SomeClass.as"

    with SomeClass.as looking like this:

    package {
        import flash.display.Sprite;
        public class SomeClass extends Sprite {}
    }
    

    Upon initialization, flash will create an instance of this class and attach it to the stage. This will be the similar to the AS2 concept of _root. The -src switch passed to mxmlc.exe sets the path to the rest of the classes/packages that support this main class.

    As such, your main class, whatever you call it, should inherit from Sprite.

    Yes. The constructor for your "main class" will be the entry point for your swf.

    ActionScript 3 class methods are automatically bound methods, which is a subtle change from javascript. In fact, its impossible to call a class method in any other context than that instance from where it was created (even if you use .call() or .apply() to try to force a context change). For example with this simple class

    public class SomeClass {
        public function Worker() {
            alert(this);
        }
    }
    

    and then

    var cls:SomeClass = new SomeClass();
    
    cls.Worker();
    var func:Function = cls.Worker;
    func();
    func.call(this);
    func.apply(undefined);
    

    Those four function invocations will produce the exact same result, because Worker() is always bound to the function it came from.

    Note, this only applies to class methods, and doesn't apply to anonymous functions/closures. So...

    var func:Function = function():void { alert(this); }
    func();
    func.call(cls);
    func.call(undefined);
    

    ...are all different

    It depends, if its a class method then it'll always be bound (see last section). If closure/anonymous function, then yes, it'll still need to be bound to specify this.

    You'll probably want to go get the flash debugging player. And the compiler should have come with fdb, the flash command-line debugger. The idea is that when you host/run your app in the debugging player, you can attach fdb to the instance and trace(), as well as set breakpoints and view exceptions.

    I'm going to have to look into this one, though I would imagine that the "proper" AS3 solution, would be to create a static method off of another class to perform this action, rather than trying to extend Array directly. Something like:

    package {
    
        public class ArrayHelpers {
            public static From(object:Object):Array {
                /* do work */
            }
        }
    
    }
    

    And then call it as: ArrayHelpers.From(whatever);