I have been a professional Flash/Flex/ActionsScript developer, designer and animator for almost 10 years now. Holding up in Brooklyn, NY I recently developed sites for the Marines, Nokia, Smirnoff and too many others to go on with a silly list like this. Originally I started out as a web designer for a video game company way back in the days of Flash 3. Luckily, I was in the right place at the right time and learned programming logic from the old-school assembly and C++ programmers there while I taught myself Flash's as it grew to version 5 and its fancy new ECMA based syntax. Feel free to check out my blog for more tutorials and scripts at: http://pajamacode.pj-co.com/.As a side note, there are some who might debate the merits of such a system of events and consider it bad OOP. While I respectfully disagree, please see this forum post to delve into that discussion if you wish.
Okay, phew -- we got that cheesy intro friendly banter paragraph out of the way, so let’s dig into the nitty gritty!
Why?
What do we hope to accomplish:
Who?
Not for Everyone. This tutorial is for the following people and/or robots:
What?
What are some of the things this system could be used for?
Not?
I don’t like to admit this in public but it’s true that there is some stuff centralized event management isn’t cut out for:
Enough already lets write some events! Make stuff happen!
Whoa, slow down there. We need to look back at why events are useful first. Remember that first time you really “got” events? That same day you got hit by lightning and managed to power your laptop without a battery or plug for hours? Yeah, it was like that for me too. Lets look at one of those o-so-fun examples of what makes events so great: The Space Balloon Attackers.
Lets say you were programming a game, one of your own original ideas that is in no way whatsoever a copy of space invaders with balloons. As you begin to code your not space invaders game, you realize that events make things super easy for you to send messages between your objects. It allows you to separate different pieces of the functionality into some logical objects and yet still talk to that main class. Your space balloons will notify the game class when then come onto the screen, and the ThumbtackCannon class can notify the balloons when it's fired a Thumbtack. Finally the balloon could notify the game class that it has been popped.
So this really makes things pretty streamlined and we can already see how events can be of help to us, but that's not the whole picture. Events try to sneak away from a problem that all code can potentially suffer from. Spaghetti coupling. By using listeners and dispatchers, events have a way of letting objects state what is important to them right up front. Basically they only need to "register to be notified later." This can be nice because it organizes the references we must keep track of from one object to another rather that having to remember that we need to call the method popReallyBigBalloonAndShowPowerUp() on the balloon class when a tack hits it.
So perhaps as you start to code, you sketch out the connections each class will have with each other. Early on with just a few objects things look something like this:
(Note: only pseudo-UML here for simplicity)
Well that looks pretty neat. We’ve got some of our basic classes and
events and we seem to be following good OOP principles.
But this is where we cue up some elevator music... ( time passes by ).... And later, when we’ve really dug into the code our classes might start to look more like this:

Oops what do we do now? Does the above diagram look familiar? Perhaps conjuring images of pasta? Yes, indeed I like spaghetti too -- I like most all kinds of pasta actually; but it’s
best eaten with some pesto or marinara sauce, not splattered all
over our code right?
Well who hasn’t regurgitated some spaghetti code at one time or another? I know I have. But that’s besides the point (and a little disgusting). Rather than talk about code upchuck, how about we see what we could do to help solve our spaghetti dilemma.
public function registerDispatcher ( dispatchingObj : IRegisteredDispatcher ) : void { /**
* Get The events
* getEvents() is a custom method that must be in any
* class/obj that wants to register as a dispatcher
*/ var eventArray : Array = dispatchingObj.getEvents ( ) ;
/**
* Add the listeners
*/ var len : uint = eventArray.length for ( var i : uint = 0 ; i < len ; i++ )
{
var dispatcherEventName : String = eventArray [ i ] ;
dispatchingObj.addEventListener( dispatcherEventName, recieveEvent )
}
/**
* Save a reference in an array.
*/ dispatchersArray.push ( dispatchingObj );
}
package com.pj_co.balloongame
{
import flash.events.Event;
/**
* Fake tutorial event!
*/ public class BalloonEvent extends Event
{
public static const POP : String = "pop";
public static const SHAKE : String = "shake";
public static const RATTLE : String = "rattle";
public static const ROLL : String = "roll";
public function BalloonEvent( type : String )
{
super( type );
}
public override function clone() : Event
{
return new BalloonEvent( type );
}
}
}
package com.pj_co.balloongame
{
import com.pj_co.interfaces.IRegisteredDispatcher;
import com.pj_co.balloongame.BalloonEvent
/**
* Balloons are best popped but we need to tell people about it!
* @author patrick cousins
*/ public class Balloon extends MoiveClip implements IRegisteredDispatcher
{
public function Balloon ( )
{
//constructor stuff here, make a balloon!
}
/////////////////////////////////////////////
/**
* Other Balloon code would go here but we're not going to include all that.
* It's a tutorial after all we're not nuts!
*/ /////////////////////////////////////////////
/**
* Required function for my custom EventManager. This tells the EventManager
* what events to listen for. The EventManager will then add
* itself as a listener to this class for these events.
*/ public function getEvents ( ) : Array { var myEventsArray : Array = new Array ( ) ;
myEventsArray [ 0 ] = BalloonEvent.POP
myEventsArray [ 1 ] = BalloonEvent.SHAKE
myEventsArray [ 2 ] = BalloonEvent.RATTLE
myEventsArray [ 3 ] = BalloonEvent.ROLL
return myEventsArray;
}
}
}
package com.pj_co.balloongame
{
import com.pj_co.balloongame.BalloonEvent;
import com.pj_co.managers.EventManager;
/**
* We Need to keep track of the score to know how the player has done!
*/
public class ScoreCard
{
private var score : int = 0;
public function ScoreCard ( )
{
EventManager.getInstance().addEventListener( BalloonEvent.POP, updateScore ) ;
}
private function updateScore ( e : BalloonEvent ) : void
{
score ++;
}
}
}
package com.pj_co.balloongame
{
import com.pj_co.balloongame.BalloonEvent;
import com.pj_co.managers.EventManager;
/**
* We Need to keep track of the number of enimies killed till we can advance to the next level!
*/
public class LevelManager
{
private var score : int = 0;
private var numBalloons : int = 15;
public function LevelManager ( )
{
EventManager.getInstance().addEventListener( BalloonEvent.POP, updateScore ) ;
}
private function updateScore ( e : BalloonEvent ) : void
{
score ++;
if ( score > numBalloons )
{
// win!
}
}
}
}

Are you amazed yet? OK, I suppose it's a bit short. But this really is key to everything. Because the EventManager is listening to an event from a dispatcher, when it hears that event, the EventManager needs to tell someone. Problem is, the EventManager isn't really sure who wants to know. So our solution is to make the EventManager a little bit like a crazy person, and make it just talk to itself. Eseentially, the EventManager recieves the event and then redispatches it to itself. Have a look at the diagram below for a general idea of how this works./**
* Re-dispatches any events received.
*/ protected function recieveEvent ( e : Event ) : void { trace( "received event:", e.type);
dispatchEvent( e );
}

package com.pj_co.events
{
import flash.display.Bitmap;
import flash.events.Event;
/**
* ImageLoaderEvent simple custom event for the image loader class
*/ public class ImageLoaderEvent extends Event
{
public static const LOADED : String = "imageLoaded";
public static const ERROR : String = "errorLoadingImg";
public var image : Bitmap
public var id : int;
public function ImageLoaderEvent( type : String )
{
super( type );
}
public override function clone ( ) : Event
{
var newEvt : ImageLoaderEvent = new ImageLoaderEvent ( type ) ;
newEvt.image = this.image;
newEvt.id = this.id;
return newEvt;
}
}
}