Big MovieClip “Duh”

Big MovieClip “Duh”

For a while, I’ve been wondering if there was a better way of catching events from MovieClips in an object-oriented context. If you use the “onEvent” hooks in MovieClip, they store only the address of your function. The way I did it in Prove It was by (taking deep breath) creating a static method in a special MovieClip wrapper class that used the this keyword as the key in a hashed array for looking up registered instance references

In other words, something like this:

 class ClipWrapper
 // Dave Seah's Magic Event Manager

  static var lookup:Array;

  static var ON_PRESS_EVENT   = 10;
  static var ON_RELEASE_EVENT   = 11;

  static function RegisterClip(clip:MovieClip, obj, method:Function)  {
   var execObj = new Object();
   execObj.obj = obj;
   execObj.method = method;
   lookup[clip]=execObj;
  }

  static function DispatchEvent (clip:MovieClip, eventType:Number)  {
   var execObj = lookup[clip];
   var obj = execObj.obj;
   var method = execObj.method;
   method.call(obj, eventType);
  }

  private var clip:MovieClip; // wrapped clip
  function ClipWrapper() {
   clip = _root.createEmptyMovieClip();
   RegisterClip(clip,this,HandleClipEvent);
   clip.onPress = function () {
    ClipWrapper.DispatchEvent (this, ON_PRESS_EVENT)
   }
   clip.onRelease = function () {
    ClipWrapper.DispatchEvent (this, ON_RELEASE_EVENT)
   }
  }

  function HandleClipEvent(eventType:Number) {
   switch (eventType) {
    ...
   }
  }

 }

This works around the problems with using the MovieClip event handlers onPressEvent or what have you…they do not execute in an object-context, so none of the instance variables are available. However, when the callback is executed, the anonymous function’s this is set the movieclip that triggered the event. And since we have a static method defined as ClipWrapper.DispatchEvent(), we can call it so it can look up the object that has registered to receive events, then call the method & restore the object context.

I thought that was pretty cool, but registering and de-registering objects in the array is a bit slow when you get to 500 or so objects (the hashing slows way down). But in a ClipWrapper managing only a few clips, lookup should be relatively fast.

Other people must have figured this out, but I wasn’t finding much online. So this seemed to indicate to me that there was a far easier way of doing it that I just was missing. After reading Essential ActionScript 2.0, I realized that this was the Mouse.AddListener function. You can track MouseUp, MouseDown, and MouseMove and roll-your-own event management this way. And Listeners are completely object friendly, unlike Callbacks.

There might still be an advantage to the way I was doing it before for making use of the built-in event masking that happens when you nest movieclips, so I’m continuing to look into it.

Extending a MovieClip directly might also get away from this problem, but I don’t like writing code that requires you to establish class linkages in the Flash Library. A foible, I know.

For the current game project, I’m using Mouse.AddListener. The interactivity is pretty limited, so I don’t anticipate having to roll things together. I’m curious what kind of benchmark improvement might occur by using a native code dispatch mechanism.