Now we'll turn our attention to the easy way to produce mock-3D motion effects using ActionScript. Having worked through the relatively straightforward tweened effects presented earlier in this chapter, you may be excused for doing a double-take at that last line. Can I really be implying that using ActionScript to create motion is easier than tweening? After all, ActionScript is supposed to be hard as hell and anyone who understands a word of it is a genius, right? Well, not really ” especially since I've already done all the hard work for you!
During the past year or so, I've been working on creating an open -source ActionScript framework for Flash MX called the Moose ActionScript Library. By the time this book hits the shelves , Version 1.0 should have already been released over at SourceForge . Although there are many modules in the framework that do all sorts of different things, the one that concerns us here is a class called Move . Using this class, you can animate any property of a movie clip over time using any movement function you like ”for example, ease in, ease out, and so on.
For instance, if you want to scale in a movie clip from 0% to 100%, just set its _xscale and _yscale properties to 0 and create an instance of the Move class where you specify that the _xscale and _yscale properties should be increased by 100%. Do you want to also make it fade in from 0% to 100% simultaneous with the scaling? Easy, just set the _alpha of the clip to 0% and tell the same instance of the Move class that you'd like the _alpha property of the clip increased by 100% at the same time. How would you like that movement, with ease in, ease out, or both? Just pass the movement function you'd like to use as a parameter when instantiating the class. The class comes with quadratic ease in, ease out, and ease in/out functions by default, thanks to Robert Penner, but there's no reason why you can't plug any movement function in there instead (for example, a circular motion function).
To demonstrate just how much simpler this way of doing things is, let's jump in and re-create the atmospheric perspective effect that you created earlier, now using the Move class. This time, instead of text, you're going to scale in a window. Before starting, make sure you've downloaded this chapter's sample files from www.friendsofed.com , which include the Moose ActionScript Library files for this project ( init.as, frame_event.as , chronos.as , and move.as ).
Open a new movie (CTRL/CMD+N), set the stage size to 500x400, and set the frame rate to 120. Since you're going to be using time-based instead of frame-based motion, setting your frame rate to the maximum will allow you to get the smoothest motion. We may never reach 120 fps, but you'll take whatever Flash can dish out!
As a side note, it's worth noting that there has always been controversy on the "ideal frame rate" for Flash. In truth, there isn't one: it's application-specific. When I write my applications, I usually keep the frame rate at 120 since all of my code is time-based. I use scripted routines even for frame-based animations, giving me complete control over the frame rate I want to play them back at (independent of the actual Flash frame rate). Thus, the higher the frame rate, the more precise my time-based calculations will be since they are recalculated every time an enterFrame event occurs. The side effect of this on slower systems is that Flash might slow down the whole system as it tries to deliver on your request for 120 frame refreshes per second. The only real solution is to test your application out on all supported platforms and on your minimum supported system specifications for each platform. If you find that 120 fps slows down the system unacceptably, then by all means lower the frame rate.
Draw a largish window. You can choose to make this as elaborate or simple as you please . We created the following window, which is 400x250px and has a ScrollPane component, from the Flash UI Components Set 1 with its content set to a movie clip that contains the picture of an adorable little kid (well, of a little kid in any case!). You can check out our version of this example, my_window.fla , in the sample files. If you want, you can very easily follow these steps with a 400x250 rectangle.
Convert your window graphic to a movie clip symbol and call the symbol my window . Using the Property Inspector, give it an instance name of win_mc .
Create a new layer ( Insert > Layer ), label it actions and enter the following script into its first frame:
// Include necessary Moose ActionScript Library modules // These modules must be saved in the same directory as your SWF #include "init.as" #include "frame_event.as" #include "chronos.as" #include "move.as" // Set the window's opacity to be completely transparent win_mc._alpha = 0; // Set the window's scale to 0% win_mc._xscale = win_mc._yscale = 0; // Create new instance of the Move class, telling it to increase // the _alpha, _xscale, and y_scale of the movie clip by 100% // and to move the movie clip up (_y) by 50 pixels in 1 second. var movel = new Moose.Move(Math.easeOutQuad, this, "win_mc", 2,{_alpha: 100, _xscale: 100, _yscale: 100, _y:-50}, true);
That's it! Test the movie to see the window fade in, scale up to 100%, and move up by 50 pixels. So in five simple steps you've accomplished what took over twice as many steps to do using tweens.
As you start to build more complicated applications, you will notice that more often than not, using a well-written script will save you lots of work over tweening in the long run (especially when it comes to customizing an animation or effect). At this point, you may be wondering what the four external ActionScript files you loaded in contain. Here's a brief explanation of each:
init.as ” Contains code that initializes the Moose ActionScript framework. This is mostly boring stuff that you never have to worry about unless you start writing your own modules for the Library .
frame_event.as ” A frame-event engine. The one thing they left out of Flash MX was a good frame event engine (for creating frame event listeners ”functions that get called every time the playhead enters a new frame). This is a simple class that fills this void .
chronos.as ” Contains time- related functions. For example, for calling a certain function every so many seconds .
move.as ” Contains the Move class we used to animate our window. More often than not, modules in the Moose framework are made up of single classes that each have their own external .as file .
Although we've outlined what these files do, you really don't have to worry about it (at least about the first three). All you need to do is learn the interface for creating an instance of the Move class. Here's the part of the signature (or definition) of the Move class constructor that concerns us currently:
moose.Move = function(movementFn, theTimeline, theClip, theDuration, deltaProps, run, nextMove, ...)
Let's analyze what this means. First off, we have moose.Move , which just tells Flash to look in the moose namespace for the Move class. All modules in the Moose framework are located under the moose namespace so that they don't accidentally conflict with built-in classes or classes from other frameworks (Moose tries, as much as possible, to play nice with other frameworks!). All you really need to know is that to create a new Move instance, you begin your statement with new moose.Move . This gives Flash all the information it needs to find the Move class and create an instance of it. Of course, you also need to pass it some parameters so that it knows details of the animation. Some of these parameters will benefit from a little further explanation:
The movementFn parameter is a reference to the function that will define how the initial properties (for example, _x , _y , _xscale , _alpha , and so on) of a movie clip are animated. There are three movement functions that come with the Moose Library, and this number will surely increase in time; they are the famous Robert Penner easing equations Math.easeInQuad , Math.easeOutQuad and Math.easeInOutQuad .
deltaProps is an object that contains the movie clip properties that you want to animate and the amount by which you want the properties changed (in math, delta represents "change in"). For example, to move a certain clip 50 pixels to the right, you would pass { _x: 50 } as the deltaProps parameter. To move it 65 pixels to the left, you would pass { _x: -65 }. You can pass any valid movie clip property using the deltaProps object, including, but not limited to, _x , _y , _xscale , _yscale , _width , _height , and _alpha .
run is a Boolean ( true/false value) that determines whether the move/animation will run immediately. If you choose not to run the move immediately, you can run it at a later time by calling the startMove() method of the returned Move instance (which, in the preceding example, you save in the move1 variable. Thus, you would call move1.startMove() ; ). Logically, you can also call the stopMove() method to stop an animation at any time.
The nextMove parameter provides a simple way of chaining together multiple moves to create a larger animation. For example, if you have another move defined as move2 that you wish to run after move1 is complete, create a Move instance called move2 and pass it as the nextMove parameter when creating move1 .
The Moose framework provides an even better way of creating complex scripted animations called MoveScript , and even the Move class constructor can accept additional arguments that we haven't covered here, but those topics are beyond the scope of this book. For those of you who are interested in finding out more, be sure to check out the final version of the Library when it is released at http://sourceforge.net/projects/moose/ .