Stop Propagating! Pt. 1 AS3, Event Handling, and Lil Timmy

I’ve periodically run into issues playing around with EventListeners where I want to remove one EL, and add another in the same function, something similar to the following code below.  First, a quick note on what’s going on in the code so we’re all on the same page.  I have a movie clip “defensive structure,” say, a tower for a Tower Defense game.  It has been added to the stage and I attached an EL to this movie clip of the tower when I added it to the stage, listening for a MOUSE_DOWN event on said tower.

Since then, I’ve added a few other movie clips INTO the tower Movie Clip.  The first issue I ran into was that normally I’ll use “e.target” as the “hey what did I click” variable to trace out or find out just what exactly was clicked.  e.target was pointing at a child of my tower movieclip, which gave me a number of errors like, “this function does not belong to this movie clip,” because functions belong to classes, and I’m targeting just a simple sprite or movie clip.

However, e.currentTarget returns the containing DisplayObjectContainer of e.target.  Usually e.currentTarget would trace out to be [object Stage], but since I specifically added e.target as a child of my defense movie clip, e.currentTarget is returning the actual object I need, the Defense object.

So, let’s take a look:

private function defenseClickHandler( e:MouseEvent ):void  {
trace( "Defensive Structure " + e.currentTarget + " was Clicked" );
clickedDefense = e.currentTarget;
clickedDefense.removeEventListener( MouseEvent.MOUSE_DOWN , activeDefenseClicked );
clickedDefense.doFunctionBelongingToDefenseClass();
clickedDefense.setClickedVariable = true;
clickedDefense.parent.addEventListener( MouseEvent.MOUSE_DOWN , activeDefenseClickedElsewhere , false , 0 , true );
}

I never remember what I do to fix this issue.  Have you had this issue

What was ‘supposed’ to happen was that I click the tower, it performs the function ( in my case displaying another sprite which represents the range of the tower ) and once clicked, I wanted to remove the EL on this specific Defense object, because clicking on it again should not change anything.  However, I wanted to Add a new EL to the stage, so that if I clicked the mouse anywhere else, it would hide this range sprite, reset the EL on the Defense object, and everything would be back to normal.

Enter Event Propagation and the Event Handling cycle of Actionscript 3.  AS3 employs this sortof catch-all boomerang system of Event handling.  When a new event is dispatched, the AS3 Event-Handling-Boomerang-of-Justice launches from the Stage.

Lets imagine your flash project is a swimming pool, and Stage would be the top surface of the water.  We’ll call the Event Listener the Lifeguard here for the sake of the analogy.  All of the other objects and text fields and movie clips and sprites you’ve added to the stage will be represented in our analogy as “The Water” in the pool.  All of those objects in the Display List, like the water, are all things that the Lifeguard/EventListener is going to have to swim through to get to the source of the event, and handle said event.  There are 3 distinct “Phases” to the way the Lifeguard is going to handle your event.  Lets roll with this analogy… I’m enjoying this.

EventListener is on it’s lifeguarding chair.  It’s been added to some object, it doesn’t care, it’s just another pool in another summer.  All it cares about is action… events.  You’ve set the Event Listener on a button listening for a MOUSE_DOWN event, or in the case of this analogy, you’re waiting to push a kid that doesn’t know how to swim into the deepend of the pool.  Sweet.

The user clicks the button triggering the EventListener, er.. as in.. you mean bastard, you shove the kid into the pool.  An Event Has Occured!  Lifeguard has an Event to handle!

Phase 1 – Capture:
Lifeguard/EventListener spots the kid you pushed in the pool waaaay down there at the bottom of the deepend (no event dispatchers were harmed in this analogy) and leaps into action, diving from its self-rightous perch at the top, and makes contact with the top of the display list/water, or in all cases, the first thing touched during Event Handling is the Stage.  The target of your event, like little Timmy, is at the bottom of the list and Lifeguard has to use the water/other objects in the display list to propel itself down the Display List/Swim to the Bottom, down to handle the event.

Now, lets stop for a second and take a look at the Event Listener.


public function addEventListener(

  • type : String ,
  • listener:Function ,
  • useCapture:Boolean = false ,
  • priority:int = 0 ,
  • useWeakReference:Boolean = false


):void

When you created the Event Listener, the third parameter passed in when you created it ( which by default is false ) is the useCapture:Boolean parameter.  This could be a whole other post just on this Capture phase. If you set this to true… the Event Listener will not care when it actually reaches the target, aka. lil Timmy.  You can have the EL listen on Capture phase, OR target/bubbling phases.  If useCapture is true, it means that you want the eventListener to respond to objects it finds and touches on the way to the target/lil Timmy.  It can get a little tricky until you wrap your head around it.  It’s taken me months of reading to finally get it ( I think! ) so I’ll pass you on to someone who’s much more confident in what all sorts of things you can use the capture phase for. Plus, there are much better visuals 😀  This is actually a damn cool post.  Interesting Use For the Capture Phase.

Phase 2 – Target:
The Target Phase occurs once the Lifeguard has made it to lil Timmy at the bottom of the pool, or in the real-life-example, once the Event Listener has arrived and is now targeting the button clicked to trigger the Event in the first place.

This is the phase that the majority of eventListeners are sitting around waiting for.  You’ve got lil Timmy, you’ve got the button, now lets Do Something with it.

But Wait!  You’re at the bottom of the pool!  The Lifeguard can’t really do anything or help lil Timmy because while it has found the source of the event… it is targeting the button… Lifeguard has grabbed a hold of Timmy… the AS3 Boomerang of Event Handling is still at the bottom of a swimming pool.  Time to come back up…

Phase 3 – Bubbling
Just as the actual name suggests, we’re bubbling our way back to the surface.  The Exact Same Path we took getting to the bottom of the list, we’re taking to get back to the top.  This is the exact opposite of the Capture phase.

On the Capture phase we were going to “Capture” the source of the Event our Listener was listening for.  At the Target Phase we arrived at that source, we found what triggered the event and we had a reference to it.  Now, we’re making our way back thru all of those movie clips and text fields and anything else directly descendent from whatever we attached the EL to in the first place. To check our progress along the way and find out which object our EventListener is touching currently on it’s way back up, we can use the event.currentTarget.

After writing all of this out, when I was using e.currentTarget to reference my Defense object, I was actually using either the Capture or Bubbling phase to get what I wanted.  Since I did not set useCapture in my EventListener to “true” I would bet it was the Bubbling Phase that I was in.  How can I be sure?


trace( e.eventPhase );

From my previous code block, anywhere in that code I can add this line.  This code now traces out,

3

A number?  Yes.  This number corresponds to the same numbering scheme using in “Phase 1 – Capture, Phase 2 – Target, Phase 3 – Bubbling.”  But because we want to completely overkill this one little issue, what is a great way to test for Sure which phase we’re in?


// make sure you import this before using any of the static constants from EventPhase
import flash.events.EventPhase;
//----
//then in our code:

if( e.eventPhase == EventPhase.BUBBLING_PHASE ) {
trace( “At Bubbling Phase” );
}
This code will make sure that we’re checking the phase # that gets returned by the constants given to us by the genius coders who created AS3.  So, thats a quick ( er… ) trip through AS3’s event handling.

I “borrowed” and edited this from Adobe’s website to fit our context.  But this is an excellent representation of what’s happening.  Also, here is the actual addEventListener method for quick reference.


Event Phase Pool

Wow.. I’ll actually have to get to the whole point of me writing this in another post.  It should show up here in the next day or so.

Oh!  And as always, that AS3 Hero Grant Skinner created a lovely & informative visual of this topic ( EventPhases and Handling ) as well.  Here’s a link to one of Grant’s slideshows of codebrainlove .  Roundabout slide 52 you’ll find an interactive model where you can step through the event phases and smack yourself on the forehead for not understanding something that simple sooner!

*smacks forehead*

FacebookTwitterGoogle+Share