THE PASZ.COM BLOG

Monday, April 10, 2006

Flash Dev Gotchas #9 - Don't Over-Engineer the MovieClip

Over the years, Flash developers have tried to follow good OOP principles, and have moved further and further to a point where their code is completely separated from the animations. Putting code in the frames of your animation is a no-no. While separating code makes good sense from an organization and maintainability perspective, when you try to use Classes to control movie clips at the frame level, there can be a performance impact. I learned this the hard way on my last project.

My grand design was to create an Anim class that would be associated with a MovieClip. The class would give me complete control over the animation at the frame level, including to do things like play the movie backwards, or to play it at half speed. My Anim class created an update callback method that updated the animation every frame (it was be called by an onEnterFrame event set up elsewhere):

public function update(){
 var cf = animClip._currentframe;
 if(animClip._currentframe < (animClip._totalframes)){
//play next frame
  actorClip.gotoAndStop(cf + 1);
 }
 else {
//reached last frame. loop back to start of animation
  animClip.gotoAndStop(1);
 }
}

The class worked well in my tests with a simple animation. But the production files that came back from the artists were much more complex, and there was noticeable lag when running the animations from my application (as opposed to running them in a standalone swf).

stop() != play()

I had assumed that I could mimic the play() function by calling a gotoAndStop() on every frame. But what I was really doing was akin to trying to play an analog audio tape on a tape player by constantly pressing and releasing the pause button -- it results in a stuttered playback.

I reworked my Anim class so it just played, instead of stopping and restarting every frame. All of a sudden, the animation played about twice as fast from within my application.

I fell into the trap of trying to over-engineer my MovieClips. There's no need to extend something that already exists and works well. Sure, if I need a particular animation to play backwards, or in slow motion, I might write a class just to handle those particular clips. Or I might even ask the artists to implement these behaviors on the timeline, perhaps even with -- dare I say it -- some code on certain frames of their animation. The latter approach might create a larger SWF, but is more likely to play back at a suitable framerate.

OOP makes it very easy to add new layers of functionality to existing objects. While you may be making your interface more elegant, you might also be creating performance problems. Especially when you're adding the new functionality to something so basic and critical like the MovieClip object. If you do create MovieClip controller classes and other frame-level mechanisms, be sure to unit test them rigorously to make sure you're doing things the most efficient way.

12 Comments: