AS3 Chronicles #3: Enter Frame Event & _root Class

You can finally add event listeners to MovieClip events. Whats more, you can register for the enterFrame event and you don’t have to have something “visual” to do it. You just create a new MovieClip or Sprite in your class, register for the event, and never add it to the Display List. In the example below, I just create a MovieClip, register for it’s enterFrame event, and pass in the function to call.

package
{
        import flash.util.trace;
        import flash.display.MovieClip;
        import flash.events.EventType;
        import flash.events.Event;
        
        public class EnterFrameTest extends MovieClip
        {
                // define our movieclip
                private var nonVisual_mc:MovieClip;
                
                // this main function gets executed when our SWF is run
                public function EnterFrameTest()
                {
                        nonVisual_mc = new MovieClip();
                        // register for the enter frame event; no Delegate, yay!
                        nonVisual_mc.addEventListener(EventType.ENTER_FRAME, onEnterFrame);
                }
                
                // event handler function, runs every enter frame
                private function onEnterFrame(event:Event):Void
                {
                        trace("enter frame");
                }
                
        }
}

That’s it!

You’ll notice there is a constructor function that is public. Like all constructors of classes, they are run when a class is created. The cool thing about this class is that it is a “main” class. Main classes are the top level class of ActionScript projects. When you compile an ActionScript Project, as opposed to a Flex Project, it uses that class as the main class, or “_root” as it were, in this case “root”, since underscores have been removed from ActionScript to clean up the API, namely in the MovieClip arena.

So, if you trace out root in your main function:

trace("root: " + root);

She’ll show “root: [object EnterFrameTest]” in the Console Window since this is your main class, and thus the true root of the SWF. To get the effect in AS2, you’d merely override _root’s __proto__ property on frame 1 of your Flash SWF, like so:

import com.jxl.controller.Application;
// do this to ensure class is exported
var depend = com.jxl.controller.Application;
delete depend;

this.__proto__ = _global.com.jxl.controller.Application.prototype;

_global.com.jxl.controller.Application.apply(this, null);// call constructor

if(this.loaded == false)
{
        this.onLoad(); // have to call onLoad manually
}

Flex does something similiar with it’s Application class.

The cool thing here is we finally have a class associated for the _root of our SWF’s, and the base class only has to be Sprite. You could use MovieClip if you wanted (I do in the example above, but always use Sprite when I can). You cannot use Bitmap, since although Bitmap does extend the DisplayObject, he is not a sub-class of Sprite. What this means is, you could create your own “MainClass”, that extends Sprite, and make that your main application class. Cool stuff!

AS3 Chronicles #2: Using Embedded Images

Remember in Flash when you wanted to use a simple bitmap? You had to:

  • import the bitmap
  • put it in a new MovieClip
  • give it a unique linkage ID
  • use attachMovie/createObject(v2) on that linkage ID

In Flex 1.5, you had to:

  • use the Embed directive above a variable
  • use createChild/Image.source using the variable

Here’s how you do it in AS3:

[Embed(source="images/Sabin.png")]
var sabin_img:Class;

var img:sabin_img = new sabin_img();
addChild(img);

Crazy!

Peter Elst show’s Chafic Kazoun’s method of using the above to “borrow” a MovieClip from an external SWF. Both of these methods are compile time only.

AS3 Chronicles #1: Simple Drawing Example

I’ve failed my 3rd try at attempting to install ColdFusion & friends, so need to prove I can actually do something out of my comfort zone. So, I’m starting an AS3 chronicles, mirroring my Flex Chronicles (2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12) to help people transition.

Drawing Example – Move your mouse around (Requires Flash Player 8.5)

DrawingMouse.as – ActionScript 3 source file

Someone on the Flexcoders list requested a Flex2 drawing example, so before I went to bed, I whipped one up real quick. Here is an ActionScript Project example of doing this in AS3, using no Flex components. There are a few key differences between Flash Player 8.5 using AS3 and Flash Player 8/7/6 using AS2. I’ll highlight the ones below via stepping through the code.

First, the stage. BIG changes are in our future for this baby. For now, you just gotta get used to stage being a variable that MovieClips/Sprites/DisplayObjects have. Don’t think of Stage as a Singleton, but rather, the display details of _root. Don’t get me started on root…

Instead of doing:

Stage.scaleMode = "noScale";

you now do:

import flash.display.StageScaleMode;
stage.scaleMode = StageScaleMode.NO_SCALE;

Instead of doing:

Stage.align = "TL";

you now do:

import flash.display.StageAlign;
stage.align = StageAlign.TOP_LEFT;

Benefits? If you mispell noScale or TL, you get yelled at by the compiler, and can more quickly fix it.

Now, for the actual drawing canvas to pick up our mouse movements:

import flash.display.Sprite;
canvas_sprite = new Sprite();
addChild(canvas_sprite);

Notice I’m using Sprite instead of MovieClip. Why? Sprite is a MovieClip, but without the timeline. If you aren’t using timeline like features, like gotoAndPlay, then don’t incur the overhead MovieClip brings; use Sprite instead. MovieClip extends Sprite so has the majority of the good stuff MovieClip has.

Secondly, I add sprite to the DisplayList via addChild. This means, “Add this sprite I just made to your display list. Each frame, the renderer will go through this list to know what he needs to draw to the screen. If the renderer finds something in your DisplayList, he’ll draw it in order from bottom to top.”

The cool part is, you can have a sprite exist, but not actually drawn. It’s like if all MovieClips/Sprites start of as myClip._visible = false, except they aren’t even drawn. MovieClips that have a visibility property of false are in fact drawn and take up resources, just not as much. This level of control makes it even more efficient.

Finally, the reason we do this is I couldn’t get mouse move events to trigger without a child clip to get them; don’t know why; if you do, please feel free to comment!

Drawing commands have been moved to graphics.

import flash.display.Graphics;
var g:Graphics = canvas_sprite.graphics;
g.clear();
g.beginFill(0x000000, 0);
g.lineTo(500, 0);
g.lineTo(500, 500);
g.lineTo(0, 500);
g.lineTo(0, 0);
g.endFill();

Notice, I just made a reference because typing “g” is easier than typing “graphics”. In earlier players, you’d do:

my_clip.lineTo(0, 0);

Now, it’s:

my_clip.graphics.lineTo(0, 0);

My favorite, adding listeners. Notice, NO FRIKIN’ DELEGATE!

It used to be:

import mx.utils.Delegate;
my_clip.onMouseMove = Delegate.create(this, myOnMouseMove);

Now it’s:

import flash.events.MouseEventType;
canvas_sprite.addEventListener(MouseEventType.MOUSE_MOVE, mouseMoveListener);

And the cool thing is, your mouseMoveListener is the actual function running in the scope of the class you’re in instead of canvas_sprite’s scope; awesome!

The cool thing to notice here, too, is that your event objects are now actual classes instead of vanilla (plain) objects; it’s an actual MouseEvent instance.

import flash.events.MouseEvent;
private function mouseMoveListener(event:MouseEvent)
{
        trace("mouse move");
        var g:Graphics = graphics;
        g.clear();
        g.lineStyle(2, 0x000000);
        g.moveTo(100, 100);
        g.lineTo(mouseX, mouseY);
        g.endFill();
}

Update: Still looking for updateAfterEvent… apparently he’s part of MouseEvent, KeyboardEvent, and TimerEvent, but it’s not in the docs yet.

Aha! It’s event.updateAfterEvent() inside the function that gets the event object.