25
Some say the days of callbacks are still going strong. Others say events just rock. Which is it? Heck, I’m not here to start a code-religion war so I’m not even going to begin to try and answer that one. Still, with all these fancy-pantsy, new-fangled events we have some big new challenges (and new opportunities too). Luckily, we’ve had some good guides in the past. Jason Cook’s great article Centralized Event Management in ActionScript 2.0 was a truly inspiring jump-off point, but now it’s time to jump a little farther and use some AS 3 in the process.
And now that I am passing my version of this EventManager along, I wanted to give credit where it’s due. And although the features of my EventManager are different, Jason Cook’s EventCenter was the inspiration to everything that follows in this tutorial.
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:
- Provide a central place that objects and classes can connect to as listeners and jam out while listening to that great new wave event music.
- Loosen the coupling in our applications and websites by allowing objects to remain unaware of each other. Loosen our ties too! (who wears ties?)
- Enable debugging of the sequence our events are firing. (what did that event just say to me?)
- Provide new functionality to remove all listeners. (Or tell all those long-winded-jabber-mouth broadcasters they need to hush up!)
- Add a new longevity feature to listeners and dispatchers. (Some need life support!)
Who?
Not for Everyone. This tutorial is for the following people and/or robots:
- Intermediate ActionScript 3 developers.
- Basic understanding of OOP and class inheritance.
- Those with a working knowledge of events.
- Banana enthusiasts.
What?
What are some of the things this system could be used for?
- Small “postcard” or portfolio websites.
- Flash games
- Interactive banner ads and Rich Media.
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:
- Complex Applications
- Projects with multiple ActionScript developers
- Anything where the complexity is enough to justify a framework
- NASA rovers
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 baloon 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.
One of the problems with Event dispatchers (also called broadcasters in AS2), is they want everyone to know about them! They aren’t content just talking to themselves. They want people to listen, and they’ll pass their event around with fancy bubbles just to disguise it. OK, I kid a bit here of course, but it’s to make a point. EventDispatchers need to have another object listening to them for their event to have any effect outside their own DisplayObject chain. Simply: they need listeners to communicate.
And here’s where the fun begins. With centralized event management we’re able to limit the number of listeners and coordinate the speeches of all those busy-body dispatchers.
Finally some code!
In the EventManager we have a method called registerDispatcher. This method is what a broadcaster would call to tell us it’s going to be broadcasting events. It’s like that HR person you send your resume to if you’re one of those busy-body, overly-talkative EventDispatchers.
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, receiveEvent ) } /** * Save a reference in an array. */ dispatchersArray.push ( dispatchingObj ); }
The key to all this is the getEvents() function. It reaches out to that object and asks for a resume of sorts. It’s the interviewer that asks the object that wants to register if it’s up for the job. When an object wants to register as a dispatcher, it has to provide a list of events it’s going to be sending out. It does this by returning an array of strings that represent the names of the events it will dispatch. Let’s look at an example:
First, since this type of event managment system is best suited for application-wide events, let’s look at a custom event our Balloon Popper game will use for letting objects know when a balloon has been popped.
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 );
}
}
}
Great! we have an event but who’s listening? No one seems to care yet? Well first no one is dispatching this event! Well now that we knoe what to say, who is going to say it? The balloon class of course. They are the objects that pop! Let’s have a look:
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 with the get events method!
* @author patrick cousins
*/
public class Balloon extends MoiveClip implements IRegisteredDispatcher
{
public function Balloon ( )
{
//constructor stuff here, make a balloon!
}
/////////////////////////////////////////////
/**
* Other Baloon 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;
}
}
}
Ah, so now we have it! That old friend of ours the getEvents() function. This is what lets everyone know what the baloon will be saying. Except that’s the trick. It doesn’t actually let everyone know. It just lets the EventManager what to listen for. We do this by returning an array that is just the names of each event we may dispatch later.
So this is still all well and good but we still dont have anyone listening! Read on to the next page to learn about how we can listen in to the events.
What what what? Who’s listening?
Now that we’ve managed to send events to our EventManager class, what does it matter? We need some objects to listen in to make this worthwhile don’t we? Indeed we do, so let’s show two objects that are going to listen in for these events.
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 ++;
}
}
}
Above was our ScoreCard class, which obviously would need to know when a balloon was popped. Below let’s look at the LevelManager class which also needs to know.
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!
}
}
}
}
Notice that all these two objects had to do was to listen to the EventManager. This is really the key of what makes centralized event management powerful. If you remember our object and event diagrams from before, can you imagine what they might look like now with such a system?

Alright now we’re talking. Looks a bit cleaner right? So we know how to register as a dispatcher, we know how to listen in, and we can see now how many objects can more easily listen to a single place without knowing where the object is that’s making the dispatch. So what’s next? Read on for a bit about how this works behind the scenes and why the clone() method is important. Then finally we’ll talk about uses and advanced implementations that will be coming in part II of this tutorial.
The Fancy Magic (behind that curtain)
Having been through a bunch of ways to implement this centralized even management I suppose some of you may want to the powerful method that makes all this work.
This method is really the magic behind everything, so as you read it be prepared for something powerful.
/** * Re-dispatches any events received. */ protected function receiveEvent ( e : Event ) : void { trace( "received event:", e.type); dispatchEvent( e ); }
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.

Before we discuss this diagram, it’s important to note again that this is only pseudo UML. Those arrows don’t actually represent events moving around but this can give us an important way to visualize what’s going on. Because the EventManager is listening to the dispatcher, the data can flow from the dispatcher (on the right) to the EventManager (center). Similarly, because the ListeningObject (on the left) is listening to the EventManager, data can also flow from the EventManger to the listening object.
The problem is, at this point the event that originates with the dispatchers has already completed. It’s as if it ran out of breath. Luckily, the EventManager can give it a second life through the clone() method in all Event classes. There are a number of tutorials online about the clone() method and how to implement it for your custom events. A lot of these tutorials however, tend to not demonstrate all of the reasons why it’s important, and this type of re-dispatching is exactly one of those reasons.
When you re-dispatch an event, Flash’s built in EventDispatcher class calls the clone() method on your old event to make a new one. If you had any type of special values in your event, such as an ID or XML object, and you forgot to override clone(), you would lose those values. This happens because Flash’s EventDispatcher will call the clone() method of your custom classes super class — the plain old vanila Event Class. And since the regular Event class has no idea that you had special values in your custom event, it will never clone them. So be sure to override clone() in your special CustomDollyTheSheepEvent class if you want to maintain those properties.
We won’t go to much into how to override the clone method when making custom classes, but below is a code sample showing a custom event with a proper clone method.
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;
}
}
}
So that’s the curtain, and what’s behind it. Click that next page link one more time for a conclusion and some info and challanges to be discussed in part II of this article.
We’re done!
Well, for now we’re done. But now that you have learned centralized event management using AS3, I bet some ideas are swirling around in your head about what more can be done with all this. What I outlined above was merely one way of centralizing the events in Flash. Can you think of others? What about different priorities to the events? Different tiers? Or maybe even resetting the event lists? I’ll cover these all in a follow up part II to this tutorial but till then You can find the link to the code used in this tutorial below as well as the complete EventManager class which might just have some of those extra features.
Drawbacks
It’s important to note that this isn’t a full-proof system. Much like any other centralization of data it can eventually grow too cluttered. With this clutter comes the possibility of collision when two events are named the same thing. Nevertheless, there are some great uses for centralized event management and I provide it to you as just another tool in your toolbox. Part II of the tutorial will also cover some of the drawbacks and ways to mitigate the potential problems.
Thanks for reading and please feel free to comment below or catch up to me in the Actionscript.org forums.
Source:
filed under: Scripts, Tutorials | permalink
11 Responses to “Centralized Event Management in ActionScript 3”
-
Andre Says:
November 16th, 2008 at 9:11 amWhat a killer tutorial, you nailed it. The clone explanation was very clear and I finally understood why to overwrite it.
Just one quick question if I may. Are the ManagerSomethingClasses usually singletons?I can’t wait for part2.
-
pj Says:
November 17th, 2008 at 2:59 amThanks for the kind words Andre. Most of the time I make the EventManager a singleton because that design pattern fits pretty well for having a “central” place to listen to events. But it doesn’t have to be, and indeed some people have strong opinions against singletons. It’s really a matter of preference. I also hope to cover some situations in which someone might want to have several instances of the EventManager in part II.
-
Andre Says:
November 18th, 2008 at 12:20 pmHey pj, thanks for sharing the code.
I was reading through the classes and I noticed that you didn’t upload the EventListenerObject class ( you create instances of it in the EventManager class ), although I think that it may only be a generic object with only one ID property ( with no real logic behind ). Either way you can delete this comment, I just wanted to make sure you didn’t forget it by accident. -
pj Says:
November 22nd, 2008 at 3:51 amThanks again Andre, code has been updated with that class and a bunch of code fixes too.
-
Andre Says:
November 27th, 2008 at 4:04 pmThanks for the updates, I’d also like to know if it’s ok with you if I post a simple application in my website using your package, I will be realeasing the code but it’s a really simple simonsays type of game made with educational purposes in mind, I use a bit of MVC principles and your EventManager class, I will of course give your deserved credits.
Thanks again.ps: those reIceive and dispaCtchers kill me man ;)
-
Jerimee Says:
December 1st, 2008 at 6:54 pmI’m trying to figure out what this is. I need an example fla file to understand how the code connects.
Is the document class “com.pj_co.balloongame.Balloon”? Do I need to create Movieclips? Do those Movieclips need to have base classes?
Sorry to be a noob. An example fla file will really light the way for me.
-
rustyleaf Says:
December 3rd, 2008 at 6:29 amHi pj,
Great stuff. Have implemented it and its listening but its not actually dispatching my events. i think this might have something to do with eh clone explanation part that I didn’t quite get…? I have not created a CustomEvent. I am using MouseEvent, but as I haven’t put it into a CustomEvent – the clone part is not in operation. Can you give me a little hint here… I am very new to this AS3 land… perhaps a CustomEvent class that extens the MouseEvent???
-
pj Says:
December 5th, 2008 at 11:19 amHey all thanks for the comments, I’ll have a look this weekend and I am also going to post a “lite” version of the event manager and an example FLA that might make a bit more sense.
@Andre, sorry for the delay in response, but yes please feel free to use this code I’m releasing it under the MIT open source license (which means you can use it in commercial and open source projects alike).
Thanks again all!
-
Andre Says:
December 7th, 2008 at 7:54 pmI made a quick symonsays game, I used MVC pattern but PJ’s EventManager class for more decoupling, the code is commented so people can read it and maybe learn the basics of this extremely helpful class.
-
Andre Says:
December 7th, 2008 at 7:54 pmthe link is http://andrevidal.com/blog/?p=23 btw :P
-
Dop Says:
January 11th, 2010 at 10:01 amThanks load for your very rich tutorial!
I’m a noobie in ActionScript as well, so far I haven’t gone very far from MouseEvent. One stupid question, would it be overkill to use this code in flash website? (click and go to this/that page etc.)
Leave a Reply
You must be logged in to post a comment.
