Better MovieClips with SwAG

MovieClips have been the stalwart workhorse of Flash since the very earliest days of ActionScript, so I’ll skip the details and gushing adoration and instead move on to some of the shortcomings:

  • MovieClips only play forward from the current frame. When building out animations without extra MovieClip functionality, playing animations backwards — a character in a game reversing, for example –requires a whole new timeline with the animation reversed. This produces a little extra memory overhead, even if symbols are re-used, but more importantly makes cross-linking the “forward” and “backward” clips challenging. For example, if a character is in a specific position on frame 5 of a “forward” animation, that frame might appear in frame 45 of the “backward” animation.
  • MovieClips only play at the global frame rate. Effectively, your game character can only run at one speed unless you include other MovieClips and then match them up, as best as possible, to the target speed.
  • MovieClips play holistically. When you play them, you must monitor their current frame if you want to stop at a specific point otherwise they’ll play all the way through. If you want to do this backwards, that’s even more work. If you want to play at a specific rate, ditto.
  • MovieClips have no triggers. If you want to know if frame 5 (or some label) has been reached, for example, you once again need to monitor the clip. Setting up multiple playback monitors is a bit of a pain.

So you can now probably guess what SwagMovieClip does.

As with most of the SwAG classes, SwagMovieClip doesn’t make assumptions about how it’s going to be used. You can either extend it:

import core.instances.SwagMovieClip;
public class myMovieClip extends SwagMovieClip {
...

…or you can instantiate it (just make sure to pass a reference to the MovieClip instance you want to control to the constructor):

import flash.display.MovieClip;
import core.instances.SwagMovieClip;
public class myMovieClip extends MovieClip {
   var swgClip:SwagMovieClip;
   public function myMovieClip() {
      this.swgClip=new SwagMovieClip(this);
...

If you’re extending SwagMovieClip, all of the class’ methods can be invoked using simply “this”. For example, to play the clip 3 times at double speed from the “startAnimation” frame to the “endAnimation” frame would look like:

this.playRange("startAnimation", "endAnimation", false, true, 3, 2);

Using the instantiation method, this would be:

swgClip.playRange("startAnimation", "endAnimation", false, true, 3, 2);

As you can probably guess, the playRange method plays from a starting frame (label or index), to an ending frame (label or index), optionally resetting to the start of the animation when done, optionally looping (including a specified number of loops), and at an optional playback speed (2 for double speed, 0.5 for half speed, etc.) This works just as well if the starting frame comes after the ending frame — the clip will play backwards with the specified parameters. Essentially, this one function covers the first three shortcomings I mentioned above.

A related method is playToNextLabel which, as the name suggests, will play the clip from its current position with the supplied parameters until the next label is detected. As with the playRange method, the label might precede the current (starting) frame. Here’s the method signature from the SwagMovieClip class showing all the parameters:

playToNextLabel(startFrame:*, includeLabelFrame:Boolean=false, resetOnEnd:Boolean=false, loop:Boolean=false, repeatLoops:uint=0, playSpeed:Number=1)

The addition of a pause method might seem a little redundant but it comes in handy when you need to determine if an active animation is currently in progress (and paused), or simply stopped. One great reason for wanting this information is to know whether to play out the remaining animation loop such as when a game character is coming to a rest after moving. In fact, games are primarily why I built SwagMovieClip (I used similar functionality to control the animations in the Sidekicks vs. Villains game).

Along these lines I also added a frame trigger mechanism, a method call that’s made whenever a target frame is reached during an animation. Here’s an example (minus the “this” or “swgClip” part):

public function myFrameTrigger():void {
 trace ("Frame 9 was just reached in the animation");
 }
 ...
 addFrameTrigger(9, myFrameTrigger);

Obviously I skipped a detail; the addFrameTrigger call belongs in a function somewhere, but otherwise this is pretty much all you’d need. In this case, the myFrameTrigger method will be triggered any time frame 9 of the animation is reached. Since the other methods (playRange, etc.) are responsible for actually starting the animation, all of their features can be used in combination with addFrameTrigger. Here’s a slightly extended example from the one above:

public function myFrameTrigger():void {
 trace ("Frame 9 was just reached in the animation");
 }
 ...
 addFrameTrigger(9, myFrameTrigger);
 playRange (10, 8);

Here we’re playing the clip backwards from frame 10 to frame 8 (all other parameters are default — no looping or custom speed), and the myFrameTrigger method should be invoked on frame 9 of the animation. To loop the animation 7 times (stopping on the last frame), at half the current frame rate, the same code would be updated to:

public function myFrameTrigger():void {
 trace ("Frame 9 was just reached in the animation");
 }
 ...
 addFrameTrigger(9, myFrameTrigger);
 playRange (10, 8, false, true, 7, 0.5);

Every time frame 9 is encountered here during playback our trigger will be invoked.

Triggers are useful for figuring out how a game character is supposed to be interacting with an environment, for example. If your game character is picking something up from a table, the target object should be “attached” to the character’s hand only when the hand animation is at a certain position. This isn’t hard to achieve by hardcoding frame values into your code but becomes cumbersome if you need to change the animation length, and even more difficult when you need to start playing the animation in various non-standard ways.

Most of SwagMovieClip‘s other functionality comes straight from MovieClip along with expected behaviours. As with any other SwAG class, I won’t recommend using SwagMovieClip unless you actually have a need for such functionality (why bloat your code?) but if you find you’re struggling with customizing your MovieClip animations then this might be worth a gander.

P.S. Thanks for another mention, Adobe!

One comment

Add Comment

Required fields are marked *. Your email address will not be published.