天天看点

Using addFrameScript() to initialise frame assets

Since I started using Flash CS3 there’s one thing that’s really been bugging me. Or to put it another way, there’s one bug that’s really been thinging me. With every project I’ve worked on this issue has come up and caught me out. That’s probably because it involves gotoAndStop().

gotoAndStop()? How can that not work?!?

Like this….

Back in the old days you could send the play head to a frame and then do things with the symbols that were in that frame. This was all pretty basic stuff and I used it all the time. Multi-state buttons were one obvious example where you could send a movieclip to a different frame to display up, over or down graphics. Avatars in games are another example with each frame being a different animation cycle - walk left, walk right, jump, die and so on.

So what goes wrong in CS3? At first everything seems OK. I mean, gotoAndStop() isn’t exactly rocket science. The problem comes when you try and address a symbol on the frame you have just sent the play head to. In the old pre-CS3 days you could just do something like this:

myMovieClip.gotoAndStop("over");
myMovieClip.label_txt.text = "BLAH";      

myMovieClip would go to the frame labelled “over” and it would set its textfield “label_txt” to read “BLAH”. Try this in Actionscript 3 and you get the following error:

TypeError: Error #1009: Cannot access a property or method of a null object reference.

The reason is, Flash can’t resolve the reference to label_txt. Initially I thought that this must be a case where I need to listen for an event but all the obvious contenders (Event.RENDER, Event.ADDED_TO_STAGE and so on) didn’t help. In the end I resorted to using hacks like waiting a frame and then hoping that I had a non-null reference to my display objects. Finally I discovered that I could put code on the timeline and that code only gets executed when all of the display objects in the frame are rendered and ready to go.

So, if I was making a class that extended MovieClip, I could just write a method that initialised each frame I would be sending the play head to and call that method directly from the timeline. Yuk. I haven’t put any code on the timeline for years and now I being forced to? That’s dirty and wrong, that is.

Luckily I stumbled across an undocumented method in the MovieClip class called addFrameScript(). This method allows you to specify a frame number and a function to execute at that frame so now I can use my frame initialisation method and inject a call to it on the appropriate frames when the instance is created.

For example, if I want to initialise stuff on frames with labels (as in the case of a movieclip that I want to use like a button with “up”, “over” and “down” labels) I can use the following code:

var i:int;
var frame:int;

for (i=0; i<currentLabels.length; i++) {
   frame = currentLabels[i].frame - 1;
   addFrameScript(frame, initStuff);
}      

“initStuff” is just a reference to a method in my class which gets called when the frame is rendered and ready to go. You might want to call different methods depending on which frame you have gone to and this can be easily achieved by looking at the frame labels:

for (i=0; i<currentLabels.length; i++) {
   frame = currentLabels[i].frame - 1;
   switch (currentLabels[i].name) {
       case "up":
           addFrameScript(frame, initUpState);
           break;

       case "over":
           addFrameScript(frame, initOverState);
           break;

       case "down":
           addFrameScript(frame, initDownState);
           break;
   }
}      

The only gotcha is that addFrameScript uses zero indexing for the frame numbers so what is thought of as frame one by the rest of the world, addFrameScript thinks of as frame zero, hence the -1 when we define the ‘frame’ variable.

Of course, using undocumented methods isn’t a particularly good idea but this is far and away the neatest solution I’ve found to this problem and hopefully Adobe will make it a documented part of the MovieClip class in the future.

This entry was posted on Saturday, May 17th, 2008 at 1:20 pm and is filed under Code. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

From:http://www.flashbrighton.org/wordpress/?p=114

继续阅读