Document Class in AS2

Aug 22 2006 Published by under Flash

One of the really cool features of AS3 is that you specify a document class which extends MovieClip or Sprite, and that class is your application. As the class extends Sprite/MovieClip, “this” refers to the main timeline, _root, _level0, whatever you are used to thinking of it as.

In AS2 I’ve been using a static main function that passes in a ref to the main timeline and stores that in order to attach things, etc.:

[as]
class MyClass
{
private var target:MovieClip;

public static function main(target:MovieClip):Void
{
var app:MyClass = new MyClass(target);
}

public function MyClass(target:MovieClip)
{
this.target = target;
init();
}

private function init():Void
{
trace(“init”);
target.lineStyle(1, 0, 100);
target.lineTo(100, 100);
}
}
[/as]

Then, on the main timeline of the fla, you say:

[as]
MyClass.main(this);
[/as]

This has the advantage of working the same in both the IDE and in MTASC.

I was always pretty happy with this until I started using document classes. Now, having to prepend “target” every time I want to attach something, etc. seems a pain. So I started playing around with alternatives. I know I’m very far from the only one or even the first one to come up with a solution for this, but I figured I’d post it, if only for my own future reference. If someone else finds it useful, great.

Here’s what I came up with, that I’m pretty happy with:

[as]
class MyClass extends MovieClip
{
public static function main(target:MovieClip):Void
{
target.__proto__ = MyClass.prototype;
target.init();
}

private function init():Void
{
trace(“init”);
lineStyle(1, 0, 100);
lineTo(100, 100);
}
}
[/as]

The code in the fla is exactly the same:

[as]
MyClass.main(this);
[/as]

And it still works just fine with MTASC.

And it’s actually even smaller and simpler than my earlier method.

What it’s doing is replacing _root’s (or whatever movie clip you pass in) prototype with my document class’s. Of course, at that point, as _root has already been constructed, the document class’s constructor will never be called. So I just omitted it and called init directly.

With this setup, the class again is the main timeline. I can attach movie clips directly there, draw directly, whatever. Works for me.

Again, I’m sure I’m not the first one to come up with this. And I’m sure others have solutions that they find better. Feel free to share them.

22 responses so far. Comments will be closed after post is one year old.

  • Tink says:

    I always just stick this on frame one

    import Application;
    this.__proto__ = Application.prototype;
    Application[ “apply” ]( this, null );

  • Tink says:

    Note that also makes a call to the classes constructor which you might want to do in your implementation and fire the init function from within there.

  • kp says:

    Nice one Tink. So the main method would become this:

    public static function main(target:MovieClip):Void
    {
    target.__proto__ = MyClass.prototype;
    MyClass[“apply”](target, null);
    }

    Pity about the array notation. This also works:

    public static function main(target:MovieClip):Void
    {
    target.__proto__ = MyClass.prototype;
    Function(MyClass).apply(target, null);
    }

    Though I’m not sure I like calling the “constructor” of something that has already been instantiated. I think I’ll stick to just calling init. But always good to get feedback.

  • […] Well almost all…Most have already heard about the new feature in the Flash 9 preview for AS3 that allows you to specify a document class (a class file for the main timeline), and if you havent heard… well now you have. This is a pretty cool feature and will do wonders for getting nearly all code off the timeline. The bummer is that its an AS3 only feature. I realize that many people have been doing this for a while now already, but I never knew it was possible to do until now.  Keith Peters, has posted a nice article on how to do this is AS2. Pretty slick! […]

  • Great minds think alike. I just posted on this last month. 😉
    http://www.dannypatterson.com/Resources/Blog/EntryDetail.cfm?id=106

    Tink, great tip on the constructor call. I’ll definately be using that in the future.

  • kp says:

    Damn, if I didn’t know me, I’d say I copied you! 🙂

  • Mundt says:

    Anyone who puts

    import Application;
    this.__proto__ = Application.prototype;
    Application[ “apply” ]( this, null );

    is a dipshit. Instantiate the object like normal, jesus. Im so sick of you morons overcomplicating everthing. IT SUCKS to not be able to specify the entry point in AS3. The application class is stupid. A static main method is good enough for java — it should be good enough for actionscript.

  • kp says:

    Please tell me more. I really value the opinions of people who start out discussions by calling me a dipshit and a moron and then remain anonymous. “If it’s good enough for Java, it’s good enough for ActionScript” is going to be my new sarcastic catch phrase.

  • Tink says:

    Well I don’t see your actaully doing that so it must be me.

    Also by application class in AS 3.0 i presume he means the Document class, which as far as I’m concerned is a great addition and a great entry point.

    I don’t see any overcomplication, and the reason I use it is for simplicity. each to their own i guess :).

    And thanks for the cuss Mundt ;). brought a smile to the end of my day.

  • steanson says:

    this __proto__ techique is pretty funky.

    I did notice that my static references to clips were left undefined.
    So i have to set static references up manually
    is there a way around this, or is it me being lazy 🙂

    so for example

    public static var dbg_txt:TextField;

    static function main(target:MovieClip):Void{
    target.__proto__ = AppClass.prototype;
    // set static debug field to refer to target debug text field
    AppClass.dbg_txt = target.dbg_txt;
    target.init();
    }

  • […] Ok, so I came across this post by Keith Peters in which he explains a way to mimic a document class in AS2. Danny Patterson had the same idea and blogged about it around the same time. […]

  • kaiphilipp says:

    Hi. Nice hint. But I have problems compiling in the flash IDE: I get one error message: The property being referenced does not have the static attribute. any suggestions?

    sincerely
    kaiphilipp

  • Hi Kaiphillipp,

    The sample supplied works great, if you are hand typing the class maybe you are missing something.

  • kaiphilipp says:

    Hi Helmut.

    You’re so right. Thank you all again. I was really missing something, replaced init with main and vice versa plus a stupid mistake in my sources. Should have gotten more sleep. Sorry for my last post. This is really great.

  • Tekkaman Slade says:

    The embed technique your using to load an image in, how would you do that for AS 2?

  • mmarch says:

    Hallo,
    first of all thank you for sharing this nice piece of code!
    I’d like to share some minor modifications that I made to use it in a project of mine.
    I didn’t want to copy-n-paste the template for every new swf, so I tried to factor out as much code as possible.
    I have therefore a generic “fake-documentclass” class that looks like this:

    class MyDocumentClass extends MovieClip {
    private targetClip:MovieClip;

    public function MyDocumentClass(tgt:MovieClip) {
    targetClip = tgt;
    }

    // we don’t have friend qualifier;
    // also, this makes the reference read-only for the child classes,
    // which is a good thing…
    public function getTarget():MovieClip {
    return targetClip;
    }

    public function run():Void {
    trace(“MyDocumentClass run() called.”);
    }
    }

    And for every new SWF I write a specific document class that looks like this:

    class ProductsDocumentClass extends MyDocumentClass {
    //
    // swf-specific private variables
    //

    public sub ProductsDocumentClass(tgt:MovieClip) {
    super(tgt);
    //
    // swf-specific initialization code
    //
    }

    public sub run():Void {
    var targetClip:MovieClip;

    trace(“ProductsDocumentClass run() called.”);

    targetClip = this.getTarget();

    // swf-specific code goes here
    }
    }

    In products.fla I write:

    var app:MyDocumentClass = new ProductsDocumentClass(this);
    app.run();

    cons:
    – two lines instead of one in fla
    – more lines of code
    – slightly more complex than the original technique
    pro:
    – the fake document class imposes MovieClip as parent class
    and requires that one stores a reference to the root movie clip
    – avoids cut-n-paste of template code.
    – I find the name “run” more appropriate for the role of the method, than “init”

    These are my 2 (euro) cents.

  • KD says:

    Why do people seem to think its new to be able to do this. You instantiate a class object and pass it a stage reference (this) in its constructor. This has been possible since 2004. Believe it or not it’s a simple simple thing.

    I’ve had to get rid of a developer because he kept doing this document class crap and all his media buys were failing. Just do it properly and stop trying to shoe horn as2 to fit the as3 model.

  • Nick Wiggill says:

    Seems dipshittery is still the rage after 4 years. BTW Keith always good to stumble back on your blog from time to time, as I’m working more outside Flash (XNA for instance) these days.