A Closer Look: Using MovieClip.addFrameScript()

A Closer Look
Documenting the Undocumented
In the initial example using the MovieClip.addFrameScript() (noted above), all I wanted was some way to have an animation play once and stop. As soon as the playhead reached the last frame, it jumped to a function named in the second parameter of the addFrameScript() method. However, I didn’t do much by way of clarifying that. So I’d like to start with a general view of the method shown in Figure 1:

Figure 1: Structure of the addFrameScript() method
Oddly, the trick to using the method effectively is not just in the ending frame to fire the function, but also in the starting frame. In looking around, one thing I found is that the method can have multiple trigger frames that launch a function. The following shows the format:
mc.addFrameScript(n1, func1, n2, func2, n3, func3);
Each trigger frame is the frame number in the movie clip minus 1. However, when you have multiple triggers, you want to play the movie clip from some starting point other than the one that fires the function. To be purposeful, I believe that using this method must take advantage of multiple animations that can be generated in a single movie clip either at different starting points and/on on different layers. In other words, anywhere in the movie clip. The general setup for this kind of functionality looks like the following:
mc.addFrameScript(n1, func1, n2, func2);
mc.gotoAndStop(1);
. . . .
mc.gotoAndPlay(seqBegin);
In this case the parameter, seqBegin is where the animation segment begins. It plays until it hits the trigger frame that fires the function that stops the animation or causes some other action.
Adding an Exoskeleton
When placing code on the Timeline or inside the MovieClips themselves, the code is hidden and unavailable to the larger structures provided by Design Patterns. So, I continue to think of the code in terms of an exoskeleton that can reach all parts of the MovieClip objects in the Library and at the same time be available for ActionScript 3.0 in ActionScript files. In order to illustrate something useful with the multiple function addFrameScript() method, I decided to continue with an example for the bellicose Wrong Way Warrior. I create three animations for an exploding grenade, rocket and mortar. The only difference is in the size of the explosion, but the animations could be as complex or simple as desired.
Taking an eight-sided star drawing, I placed it into a graphic symbol. Then, I created a MovieClip giving it the class name Boomer. It used motion tweens to expand the graphic star from small to large. Depending on the weapon, the explosion varied. Figure 2 shows the MovieClip’s timeline with the motion tweens:

Figure 2: Animated Explosions in MovieClip
Each tween was either 5 or 6 frames — explosions are quick and short. Further, each started in a different position on the timeline and on a different layer. Given that the same symbol was re-used on all three, I suppose I could have put them all on the same layer, but it was clearer to place the tweens on separate layers.
Once that was done, all I had to do was to write a script that made use of the animations in the MovieClip object. Because I set it up for Export for ActionScript, I was able to address each in turn. (The example is a test bench, and they are not integrated into the Wrong Way Warrior or connected to sounds.) The following script shows how the ActionScript controlled the MovieClip’s playhead movement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | package { import flash.display.MovieClip; import fl.controls.Button; import flash.events.MouseEvent; public class AddScript extends MovieClip { //Create MovieClip instance private var boomer:MovieClip=new Boomer(); //Starting frame private const THROW_GRENADE:uint = 1; private const FIRE_ROCKET:uint = 7; private const LAUNCH_MORTAR:uint = 12; //Frame to trigger function (minus 1) private const GRENADE:uint=(6-1); private const ROCKET:uint=(11-1); private const MORTAR:uint=(17-1); //UI private var grenade:Button=new Button(); private var rocket:Button=new Button(); private var mortar:Button=new Button(); public function AddScript() { setUI(); boomer.x = 250,boomer.y = 200; boomer.addFrameScript(GRENADE,ceaseFire, ROCKET,ceaseFire, MORTAR,ceaseFire); boomer.gotoAndStop(1); } private function setUI():void { grenade.x = 10,grenade.y = 20; grenade.label = "Throw Grenade"; grenade.addEventListener(MouseEvent.CLICK,fireWeapon); addChild(grenade); rocket.x = 10,rocket.y = 50; rocket.label = "Fire Rocket"; rocket.addEventListener(MouseEvent.CLICK,fireWeapon); addChild(rocket); mortar.x = 10,mortar.y = 80; mortar.label = "Launch Mortar"; mortar.addEventListener(MouseEvent.CLICK,fireWeapon); addChild(mortar); } private function fireWeapon(e:MouseEvent) { addChild(boomer); var weapon:String = String(e.target.label); switch (weapon) { case "Throw Grenade" : boomer.gotoAndPlay(THROW_GRENADE); break; case "Fire Rocket" : boomer.gotoAndPlay(FIRE_ROCKET); break; case "Launch Mortar" : boomer.gotoAndPlay(LAUNCH_MORTAR); } } private function ceaseFire():void { boomer.gotoAndStop(1); removeChild(boomer); } } } |
In setting up the constants for the values where the timeline position would fire the functions, I used expressions to remind us that the addFrameScript() function uses a zero-base numbering system for frame reference. That is, the first frame is zero (0), and all of the rest are the frame number minus 1.
Why Undocumented?
It always makes me nervous to get too close to an undocumented feature in ActionScript 3.0. That means at any moment the method will be deported like an unwanted immigrant. However, the method has been around since Flash CS3 and I’ve seen it referenced in some Flex listings. Why it remains undocumented is a mystery to me, but I hope that they decide to keep it or replace it with a documented method that allows direct access to the timeline with code that is in an ActionScript 3.0 file in either Flash or Flex (Flash Builder).
As an alternative to onEnterFrame(), this method is much cleaner and far less processor intensive. It patiently waits until the playhead reaches the trigger and then launches the appropriate function. Compare this to the onEnterFrame() method that keeps running back and fourth asking, Are we there yet? like some annoying kid in the back seat.
In the meantime, the addFrameScript() method is quite valuable for developers who want to free themselves from the limitations of script on the Timeline and keep all of the advantages of controlling the play on the Timeline. If you feel the same as I do, we can launch a whining campaign at Adobe—just like the annoying kid in the backseat.
Related posts:

Bill Sanders
Thanks for explaining this cool feature which I had no idea existed. I can see it being very useful when dealing with animated MovieClip assets … eg. a game where you want to know when the player’s ship has finished blowing up. The one thing that seems awkward is having to reference the exact frame number.. wish there was a way to use a frame label instead.
My own project is going to be very dependent on being able to make things happen like this. I haven’t tried to write the code yet, but I was assuming I could make the code finish playing an animation and then jump to a function using event dispatches. Is this not the case? Thanks.
Barbara
Hi David, You can do the following if you know that certain labels exist in a movie clip.
The following class extends an MC on the stage that has two labels called ‘start’ and ‘end’ on the tween.
Now you can safely modify the tween lengths etc. knowing that the code references the labels and not explicit frame numbers.
Hi David & Barbara,
@David–I couldn’t improve on Chandima’s comment except to add when using variables you’d want to change the constants to variables. Like you, I’ve only recently learned of this method even though it’s been out for a few years.
@Barbara–Essentially, the MC playhead is acting like a trigger. As soon as it hits the frame, the function is going to be called and it doesn’t matter what you put in the function. I can imagine an endless number of scenarios for this method.
Kindest regards,
Bill
Hi Bill and Chandima,
Thanks for the tip about the playhead. I figured out how to use addFrameScript() with an event dispatch and thus avoid having a script on the timeline, and it certainly is cool! I made a little app that has 3 colored balls moving across the stage. When the red one gets to the end of its timeline, it triggers the green one etc. Here’s the URL: http://bitsong.com/forPosting/dispatchTest/dispatchTest.html
Here’s some of my code: I include Main.as and one of the colored ball classes, RedBallContainer.as Your blog is a great place to get exciting new ideas! Thanks.
Barbara
Hi, David!
Do you happen 2 know if there are any other undocumented function like the one u described?
Nice post, but one thing needs to be said!
Lets say you have some code on your timeline, for example a stop(); function call, and then after discovering this amazing function ( addFrameScript()) you decide to give it a try. Remember that the timeline code will be completely overwritten!
So its one or the other, not both!
Hi Otavio,
Yes, you want to clear the code from your timeline. That is the point. It’s bad enough having timeline code all over the place and playing “Where’s Waldo?” with your code. To have a combination of both code in a class (or a design pattern) and on the timeline is a nightmare.
Remember—now there’s no reason to have code on the timeline. Ever.
Kindest regards,
Bill
In digging into this method I found that the function that is added to the frame doesn’t have a parent, when you look at the variable parent you see “SecurityError: Error #2000: No active security context.”.
Interesting, No?
Hi Jim,
That is an interesting finding. I’d think that MovieClip is the parent. It operates as though it is, but because it’s an undocumented method, there’s no way to know for sure.
Let me dig around and see what I can find. Thanks for sending us that little gem!
Kindest regards,
Bill
A cleaner way to do this that doesn’t rely on undocumented methods or risk security concerns is posted here http://www.developria.com/2010/04/combining-the-timeline-with-oo.html
Hello Amy,
I read your article, and there is one glaring problem with it: You don’t have a single working example! Your discussion of the issues is brilliant, and I urge our readers to take a look at it.
A couple things worth discussion are:
1. What security risks (concerns) are you talking about? Is it the generic concern about undocumented methods or is there something specific?
2. Getter/Setters–Not so sure about these guys. They’re old school, but you need to take care with them. See http://typicalprogrammer.com/?p=23 for an interesting critique.
3. Avoid Export for ActionScript? Not sure about your point here. It could be that while my post was about slipping in an undocumented method to fiddle with the Timeline, most of the classes I make within Flash are just static images set up as Sprites.
4. I avoid conditional statements if at all possible, including switch statements (except for the Chain of Responsibility pattern) and you seem to be recommending checking and re-checking state with conditionals swarming like octopi ready to tangle up code and blast everything with octopus ink—not to mention slowing things down.
Anyway, loved your post, but I really would like to see an example that works! How about it?
Kindest regards,
Bill
Sorry. I didn’t realize that they stripped the comments when they moved to DevelopRIA from InsideRIA. Check out http://flexdiary.blogspot.com/2010/04/sample-code-for-oop-timeline-insideria.html or http://www.meetup.com/atlflex/files/ (these are actually different examples, and the second link has a preso).
1) See the above comment from Jim Daniel.
2) I think that the article you pointed to was talking about a totally different issue, and honestly I’d suggest you follow the link to the original Java article and make sure you fully understand it. For convenience, here’s the link http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html.
The thing is, whether you explicitly declare a getter/setter pair, check the “declare stage instances automatically”, or just use public vars for your timeline instances, the compiler is making a getter/setter pair for you under the hood. The question is, will you use it or turn your back on it out of some misplaced dogmatic puritanism?
The getter/setter implementation discussed in the article is pretty much a direct port of the Flex Code Behind pattern, where you provide instance variables that are populated by the MXML extension of the class. Like Flex MXML objects, variables that accept Flash stage instances must be public. It’s just a fact of life enforced by the language we’re writing in.
So we’re providing getters and setters not (or not solely) for other code, but for the Flash player itself to use once it has gotten good and ready to provide the finished instance it has so kindly made.
3) I did not say avoid Export for Actionscript, but to avoid Export for Actionscript in FRAME 1. This allows the Class definition to be embedded at whatever frame the symbol is first placed on the timeline and reduces startup time. In many movies, it can eliminate the need for a preloader.
4) There is no reason you can’t implement with a Chain of Responsibiility instead of a switch statement if that is what your heart desires. I have a functional implementation of a Chain of Responsibility that combines the concepts suggested here http://blog.iconara.net/2008/03/30/separating-event-handling-from-event-filtering/ with the approach suggested in the comments to http://www.as3dp.com/2008/01/14/actionscript-30-chain-of-responsibility-design-pattern-decoupling-request-and-request-handler/ by Timbot. Using such a chain, this would be quite easy, but I suspect that the performance would be somewhat worse than just a simple switch. It’s on my to-do list to benchmark switch vs. a functional chain of responsibility, but I haven’t gotten there yet.
You could also use Robotlegs (which I think is the only automated dependency injection microarchitecture that consciously maintains compatibility with pure Flash) to perform the same task, at probably an even heavier performance cost.
What I suggested was an absolutely minimal implementation to get the job done. To quibble with the specific approach suggested misses the larger concept and how it resolves the actual problem.
So let’s back up a moment and look at what the actual problem is and how I feel your solution completely misses the mark.
The actual problem is that when CS3 was released, the Flash team failed to document how you can use the timeline, yet keep clean OO code. This caused the entire Flash/As3 community to leap to the conclusion that real coders who care about OO purity don’t use the timeline. I applaud you for having the cajones not to swallow this as gospel, but I believe your solution above doesn’t address the issue.
The reason we’ve been given for avoiding frame scripts is that it makes it hard to find your code, but I don’t agree with that as the sole reason. The fact is that a frame script doesn’t belong to any real object and lives “outside” the OO paradigm. So essentially what you’ve done is add a frame script, but you told yourself it was OK, because it was housed in an as file and was added programmatically (bonus points to your programming studliness because you added it through an undocumented function).
I can see, looking at your code, that you weren’t confident that you could just put the boomer on the timeline and know when and how to address it in order to make it work…you felt you had to add it through code to get your hands on it, so to speak. Using one of my approaches, you could simply place a boomer on the stage where you needed it and go from there. You could also simply place your buttons on the stage and allow the Flash Player to instantiate them where you visually placed them and tell them when they were ready.
As you say yourself:
“When placing code on the Timeline or inside the MovieClips themselves, the code is hidden and unavailable to the larger structures provided by Design Patterns. So, I continue to think of the code in terms of an exoskeleton that can reach all parts of the MovieClip objects in the Library and at the same time be available for ActionScript 3.0 in ActionScript files.”
If you use a cleaner OO approach, where any object you need extends an actual AS Class with no wonky or hidden bits, all code is accessible to your Main Class.
I’ll leave it as an exercise to the reader to determine if there could be situations where adding a frame script could cause a memory leak, since that’s only tangentially related to the design considerations.
Hi Amy,
No one ever accused you of not being the plucky one. (Go Bulldogs!) Anyhow….let me provide you with some more context. In working with design patterns I eschew using a lot of the kinds of coding you’re talking about not for the reasons you give, but rather for the whole issue of reusability.
You talk about a “cleaner OO approach where any object you need extends an actual AS Class with no wonky or hidden bits, all code is accessible to your Main Class.” Not sure what you mean by that other than your AS lexicon is based upon structures resting on top of an Object Object (or whatever is at the top level). Accessibility to Main Class–what’s that? The automatically generated folder in Flex that does exactly what? Is that your Client making requests from within your structure? If so, I would think that it is misnamed–though automatically convenient I agree. (Surely not dogmatic puritanism…to hang on to a file name left over from a C convention.)
As for leaving things on the stage, I don’t agree with you at all nor with your characterization that it stems from adhering to ActionScript 3.0 as being somehow sullied by such action (same with code on the Timeline.) Try re-using it. Whip that baby out, and with a different application that does something other than your original, and you’re pretty well stuck…with the original and the task of redesign from scratch.
This entire post (about the use of the addFrameScript() method) is to preserve the reusability through the ActionScript code off the timeline. However, the point that using addFrameScript() requires movie clips in the Library may actually make that a somewhat arguable point. After all, if one leaves it in the Library, why not just leave it on the stage? What you code is what you see. In the Library, you’re “seeing” classes by instantiating them in ActionScript. All code on the Timeline, including the sweet little stop() statements, are hidden like trolls under the bridge–often with the same surprises in store.
Kindest regards,
Bill
I referred to the Main Class for analogy, not saying that was what you always had to use. There are enough examples out there that refer to this that it is a convenient way to speak. I am not talking about a Client relationship here, but instead am talking about using the Flash Player itself is the Factory. However, the Factory doesn’t have the information to finish the job of injecting all of the information the budding instance needs, and my post was about finishing that job.
On closer consideration of your post, it resolves a slightly different problem, which is how to react to changes in state of the object that are performed by the Flash Player, which again we don’t control.
You can choose to put stop() in the constructor of the base Class if that concerns you, but I view a Library symbol/timeline instance a bit differently than you do. The symbol + its base Class is the entire implementation of the Class, as the symbol actually extends the AS. As long as the full implementation supports the intent of the Class, other Classes don’t need to care how that is acheived.
For your example, I would have been using programmatic tweens and hence would not have encountered the problem at all (most tweening libraries generate events or have callback functionality to handle this). However, the larger issue of how to react to changes in State that you have chosen not to control and that the Player does not announce with events still remains and is legitimate–plenty of people choose to use the timeline for animation rather than choosing to use it mainly for layout, which is my preference.
I would suggest that Boomer Interface should have an onFiringComplete callback property, which would allow the parent Class to simply pass that function in and allow the child Class to call it as needed. If the implementation of the Child Class adds a frame script, has a frame script (added by normal means) that dispatches an event that it then catches prior to calling the callback, or whatever, that is its OWN responsibility, and of no concern to the parent.
Now, you can choose to directly instantiate boomer, as you have done in your example, or you can choose to drop a Boomer (and your buttons) instance on the stage and inject the callback once the Player informs you it is ready. In this case, since the main mc doesn’t have any need for multiple frames and boomer will be created prior to the constructor, you can simply address it and the buttons in the constructor, as you do. The setUI() method now becomes much simpler, because it is only concerned with adding the listener and label to each button.
Now let’s consider the reusability implications of doing it as I suggest. If you wanted to have your buttons laid out horizontally, you simply provide a different fla that extends the base class, and lay out the buttons differently. Done. Want the boomer in the center? Same thing.
Want a Boomer where the animations are 5 frames longer? You only change Boomer, not Boomer and the parent.
_You_ may not fail to use the timeline because you think that doing so somehow marks you as not a “real” programmer, but I can assure you that there is a pervasive sentiment in the Flash community that even touching the timeline marks you as a “designer” who has no idea about good OO principles, rather than someone who has considered all available information and come to a different conclusion. I’m working very hard to change that, and I’ll even hijack your blog comments to do so if I think I can get away with it
.
Hi Amy,
Love your comments, but I’ve got to finish up the series on choosing a design pattern today. However, here are a couple of points you may want to consider:
1. You keep talking about “extending” and you might want to consider “composition”–a different mind set.
2. Keeping code off the timeline has nothing to do with “marking oneself as a real programmer.” Code on the timeline isn’t conducive to either re-usability or visibility. That’s why I like the addFrameScript() method — I find it more reusable and visible.
3. Why not take a design pattern (any one, it doesn’t matter) and create an app that works with code on the Timeline in AS3? Now that would be a fun discussion and you could make your point in an example.
Kindest regards,
Bill
1) The practical implication of declaring a base class in AS3 is that the symbol in the library does extend the base Class, period. That’s simply how it works
. The base Class is the Abstract Class, if you will, and the symbol is the concrete implementation. If that symbol contains other library symbols or makes use of, for instance, a data Class, it also uses composition. If you looked at the example with the sliding photos, each PhotoFrame on the stage composited a BitmapData (actually two, but one was impled) and a TextField. But it also extended the PhotoFrame.as base Class.
2) I am not suggesting putting code on the timeline–quite the opposite. I am suggesting using the timeline to place objects–both temporally and physically–and using code to control those objects once Flash has done the hard part of instantiating them.
3) Again, I am NOT suggesting using Timeline code. I have already expended loads of words trying to explain this. I think part of the issue is that I keep using words that I know are on your current list of concepts you don’t like and expecting you to look past them to the larger concepts and their actual meanings. Sorry bout that.
But to answer your question, you’d use these Classes, since they are perfectly ordinary OOP Classes, the way you’d use any View Class…you’d just do less work in setting it up.
Hi Amy,
Tell me about your “base class” (God forbid, I think we may agree.) I use the library for my Sprites (convert the ‘base’ class of the MovieClip symbol to a Sprite by changing the path to Sprite–why drag a timeline along when you don’t need it?). Then, I initialize instances as a Sprite and implement them as the concrete object name in the Library. In that way the Sprite is the interface (or abstract class if you wish), and I can keep things loose.
I still don’t see why you put objects on the Timeline. Why not just leave them in the library and use them when they are needed–this would include both Sprites and MovieClip objects (along with components.)
Kindest regards,
Bill
I often just leave the “Base Class” field in the library symbol blank and let the “extends” keyword in the .as Class tell the symbol what it is. If I need a timeline (or if I forget) the as will extend MC, otherwise it will extend Sprite. So I often forget that’s a separate field. When I say “base Class”, I’m not talking about that field, but the one above it, labeled simply “Class.”
Usually my View Classes are a bit more complex than a simple Sprite. For instance, I might have a QuestionView that shows a Question and allows a user to answer it, so you’d need to provide it with a stem and a set of choices. When a choice is clicked, the QuestionView will generate an event that says what answer was chosen. This is all provided as part of the QuestionView’s API (ok, events are not explicit due to the nature of Flash, but you know what I mean) and that’s all the parent really needs to know.
If the Question Stem is a stage instance, the distractors are drawn dynamically (because we don’t know at design time hoe many we’ll need) and the Submit button is a stage instance, the parent doesn’t need to care.
There are several reasons to put objects on the stage/timeline
1) It gets a picture in front of the user much more quickly. Because you don’t have to embed everything prior to Frame 1, only the objects you need to display or use immediately need to be embedded there.
2) It’s easier to see what is going on. You can actually see where things are without digging through as code and try to visualize where on screen something will wind up where myThing.x=200; myThing.y=500.
3) It’s less work. If you get a comp where the button is in a particular spot, just convert that button to a MyCustomButtonClass and it’s where it needs to be on stage, relative to all the other visuals that came in with the rest of the comp on the frame where you needed it to be. No more “that’s a bit too far to the left, what if I add 10px? No, maybe 8.”
4) You don’t have to export so many things for actionscript and address them through code. Since you leave most instantiation to the Player, you only address the objects that you actually need to interact with.
5) It’s more reusable. Since the the placement of visual elements is not handled through code, you can use a different layout by attaching the base Class to a different symbol. And child symbols can be totally different implementations of the same Class and the code doesn’t have to change. So, if you have a symbol that extends QuestionView and it uses blue Comic Sans and another QuestionView that has red Helvetica, you can have a Quiz symbol that embeds one and a different Quiz that embeds the other, and your Quiz code and your Course code don’t have to care.
By contrast, if your Quiz handles the instantiation of questions, when it uses the new operator it will have to know whether it is creating a RedQuestionView or a BlueQuestionView. Granted, you can mitigate this with a Factory, but somewhere along the line something in your as code will need to make a decision of what to make. Using the timeline/stage, nothing in your as code ever needs to know that there are two separate implementations of a QuestionView. You simply handle it very intuitively and visually by creating a Quiz that plonks either a RedQuestionView symbol or a BlueQuestionView symbol on the stage, and it’s referred to in the code as a QuestionView.
6) Thrift. I paid for that Flash IDE dammit (ok, not really but I could have), and that IDE has wonderful visual/temporal layout tools. Throwing those away is wasteful of my resources and an insult to the smart people who worked so hard to provide them.
7) I’m wired that way. I spent 10 years programming in an environment that’s essentially a flow chart (Authorware). I want to see the thing that happens first, first. The thing that happens second, I want to see second. If the project has storyboards, it has a strong temporal quality, and I want to represent that temporal quality in a way that makes sense–on the timeline.
I love that you’re willing to engage on these topics and keep going back and forth until both parties come to a mutual understanding of each other’s position. Too many bloggers/authors are quick to dismiss others, and I highly respect that you aren’t like that.
I look forward to your next installment of choosing a design pattern
.