Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning ActionScript 2.0 2006

.pdf
Скачиваний:
105
Добавлен:
17.08.2013
Размер:
12.47 Mб
Скачать

Chapter 16

Try It Out

Experimenting with Frame Rate

This exercise demonstrates the effects of frame rate on animation.

1.Open the completed tryItOut_onEnterFrame.fla file from the previous Try It Out exercise, or open tryItOut_onEnterFrame.fla from the book’s source files at <source file directory>/Chapter 16/.

2.Select File Save As, rename the file tryItOut_frameRate.fla, and save it to a folder of your choosing.

3.Select Control Test Movie.

4.Select Modify Document and change the frame rate to 24 fps.

5.Save the file and select Control Test Movie.

6.Select Modify Document and change the frame rate back to 12 fps.

7.Click the first frame in the timeline, open the Actions panel, and enter the following ActionScript code:

this.createEmptyMovieClip(“holderClip”, this.getNextHighestDepth()); holderClip.attachMovie(“circleClip”, “circleClip”, ;

holderClip.getNextHighestDepth()); holderClip.circleClip._x = 10; holderClip.circleClip._y = 10;

var intervalID = setInterval(animateCircle, 10); function animateCircle()

{

holderClip.circleClip._x += 10;

if (holderClip.circleClip._x > 250)

{

clearInterval(intervalID);

}

}

8.Save the file and select Control Test Movie.

9.Select Modify Document and change the frame rate to 24 fps.

10.Select Control Test Movie.

11.Select Modify Document and change the frame rate back to 12 fps.

12.Update the ActionScript code by adding the following bold line:

function animateCircle()

{

holderClip.circleClip._x += 10; updateAfterEvent();

if (holderClip.circleClip._x > 250)

{

clearInterval(intervalID);

}

}

378

Using ActionScript for Animation

13.

14.

15.

Save the file and select Control Test Movie.

Select Modify Document and change the frame rate to 24 fps.

Select Control Test Movie.

How It Works

The first two times this exercise is tried, it uses the onEnterFrame function, which is tied directly to frame rate, so when the frame rate increases, the animation is smoother, but takes less time to complete.

The next two times use setInterval(). When the frame rate increases, it does not affect how long it takes for the animation to complete, but it does improve the smoothness of the animation.

The last two times use setInterval()in conjunction with the updateAfterEvent() global function. When the frame rate is increased, there is no difference in either the time taken for the animation to complete or in the smoothness of the animation.

Which Technique Should You Use?

The choice of which technique to use is largely a personal one. The onEnterFrame way of doing things is convenient and is easy to set up, and most scripted animations are not really that sensitive to frame rate. For the most part, you will likely set the frame rate once and leave it at that.

setInterval()lends itself better to smoother animations, especially on machines with slow processors such as PocketPC-based devices. If you need animations that require a certain amount of time, regardless of frame rate, setInterval() is also the way to go. Finally, if you are animating an action game, setInterval() gives you the best response from keyboard input.

Choosing a Frame Rate or Update Interval

Choosing a frame rate or an update interval is actually fairly arbitrary, but a few guidelines will help.

Frame rate has an impact on both the smoothness of the animation and the performance of the playback. If the frame rate is very low, the animation playback will be slow enough that the eye can detect individual movements rather than seeing the animation as one continuous motion. If the frame rate is too high, playback performance becomes an issue where the CPU becomes too taxed and playback becomes jerky. The default frame rate for a new Flash document is 12 fps (83 milliseconds per frame). This is generally too slow for smooth animations. Compare this with some common refresh rates:

Movies projected in a movie theater run at 24 fps.

Online video generally runs at between 15 and 30 fps.

Television runs at 30 fps using interlacing.

Video games can run at between 30 and 120 fps.

Computer monitors update the screen between 60 and 120 times per second.

The human eye is capable of distinguishing between different frame rates beyond 120 fps.

379

Chapter 16

These values ignore differences in how a projector, a TV, and a monitor project their images and are perceived by the human eye; however, it is enough to know that 12 fps is too low.

Flash has an upper limit of 120 fps (8 milliseconds per frame). In general, if you set the refresh rate that high, Flash does not actually give you that refresh rate. It instead drops frames in an unpredictable fashion, making performance worse than it might at a lower refresh rate.

Setting the frame rate between 24 and 50 fps (42–20 milliseconds per frame), depending on the hardware demographics of the target audience, is the optimal range.

When choosing an update interval specifically for the setInterval() technique, keep the following in mind:

Setting a specific update interval does not guarantee that the function will actually be called right at the specified time. The actual timing may vary by 10 milliseconds or more, depending on how heavily the processor is being used.

In general, 10 milliseconds is the minimum value that can be used. Below that, intervals become imprecise, and processor issues will likely keep the actual update interval at 10 milliseconds or more.

Setting a setInterval() refresh rate of 20 to 42 milliseconds generally leads to the best results.

Creating Animation with Movie Clips

All right, enough of the pre-work. Get to some of the fun stuff! The examples shown so far are pretty boring. So far, you have just moved a movie clip in a straight line. Now you start with animating properties, animating multiple movie clips, and introducing other kinds of motion.

Try your hand with a project to explore a number of animation techniques, including basic motion, movie clip duplication, and randomization. The project you are going to create right now is a snow effect that will end up looking something like Figure 16-4.

Start with animating a single flake of snow. Use onEnterFrame, although you could use setInterval() here just as easily. Following is the base animation code, which assumes that there is a movie clip in the library with the linkage ID snowFlake:

this.createEmptyMovieClip(“holderClip”, this.getNextHighestDepth()); holderClip.attachMovie(“snowFlake”, “snowFlake”, holderClip.getNextHighestDepth()); holderClip.onEnterFrame = function()

{

this.snowFlake._y += 4;

if (this.snowFlake._y >= Stage.height)

{

this.snowFlake._y = 0;

}

}

380

Using ActionScript for Animation

This code first creates a movie clip to hold the animation. It is generally a good idea to have a movie clip to hold any movie clips being animated. This better contains the movie clips for re-use and for increased flexibility.

Next, the code attaches a single snowflake from the library and starts moving it downward. When it hits the bottom, it moves the clip back to the top.

Figure 16-4

Animating Multiple Movie Clips

So far, the code does not do very much, and there are not very many snowflakes yet. Creating more snowflakes is a process of attaching more movie clips to the stage. Every time a snowflake is added, the animation code needs to keep track of it. This bogs down the processor, so you have to be careful of how many to create.

The easiest way of creating snowflakes in such a way where it is easy to keep track of them is to use a simple numbering system. Here, you call the first clip snowFlake0, the next one snowFlake1, and so on. You can later refer to clip n using the associative array syntax:

var thisFlake:MovieClip = holderClip[“snowFlake” + n];

From inside the onEnterFrame loop, you can refer to this instead, because this refers to the parent movie clip, holderClip:

var thisFlake:MovieClip = this[“snowFlake” + n];

381

Chapter 16

With this system, it is easy to loop through the clip for each snowflake. Make a few more snowflakes:

this.createEmptyMovieClip(“holderClip”, this.getNextHighestDepth()); holderClip.maxFlakes = 100;

for (var i:Number = 0; i < holderClip.maxFlakes; i++)

{

holderClip.attachMovie(“snowFlake”, “snowFlake” + i, ; holderClip.getNextHighestDepth());

}

holderClip.onEnterFrame = function()

{

var thisFlake:MovieClip;

for (var j:Number = 0; j < this.maxFlakes; j++)

{

thisFlake = this[“snowFlake” + j]; thisFlake._y += 4;

if (thisFlake._y >= Stage.height)

{

thisFlake._y = 0;

}

}

}

Now, you have 100 snowflakes being created, and each time through, the loop goes through each snowflake and increments the y coordinate.

Some problems still exist with this code. One of the issues is that all 100 snowflakes start in the same spot, making it look like there is only one flake.

Adding Random Behavior

This calls for random assignment of x and y values, so that all the snowflakes are spread across the screen. You can use a built-in static method of the Math class, called random(), for obtaining random values. This method returns decimal values in the range from 0 to 1. Most of the time you need to work with wider ranges of values, so some transformation of the output is needed. Here is a simple function that transforms the output from this method to a random value between any range of numbers that you want:

function randomRange(min:Number, max:Number)

{

return Math.random() * (max - min) + min;

}

This is an extremely handy function. Use it any time you need to work with ranges of numbers. Apply this to your evolving snowflake code:

this.createEmptyMovieClip(“holderClip”, this.getNextHighestDepth()); holderClip.maxFlakes = 100

for (var i:Number = 0; i < holderClip.maxFlakes; i++)

{

holderClip.attachMovie(“snowFlake”, “snowFlake” + i, ;

382

Using ActionScript for Animation

holderClip.getNextHighestDepth()); holderClip[“snowFlake” + i]._x = randomRange(0, Stage.width);

holderClip[“snowFlake” + i]._y = randomRange(0, Stage.height);

}

holderClip.onEnterFrame = function()

{

var thisFlake:MovieClip;

for (var j:Number = 0; j < this.maxFlakes; j++)

{

thisFlake = this[“snowFlake” + j]; thisFlake._y += 4;

if (thisFlake._y >= Stage.height)

{

thisFlake._y = 0;

}

}

}

function randomRange(min:Number, max:Number)

{

return Math.random() * (max - min) + min;

}

Now, you are finally starting to get somewhere! You add a few more features to this code in the next Try It Out exercise.

Try It Out

Creating a Snowstorm

In this exercise you animate multiple movie clips using the techniques that you have learned so far.

1.Create a new Macromedia Flash document.

2.Open the Library panel (Window Library) and from the menu at the top right of the panel, choose New Symbol.

3.Within the New Symbol dialog box, set the name to be snowFlake. Make sure the Movie Clip radio button is selected. Click the Export for ActionScript checkbox to select it. If you do not see the checkbox, click the Advanced button on the bottom right of the panel to reveal additional options. Click OK.

4.Select the Oval tool from the Tools panel (Window Tools). From the color wells, select white for the fill, and choose the no line option from the line color chooser. Draw a roughly 6 pixel by 6 pixel circle on the stage within the new movie clip. You may need to select the shape once you have made it and use the width and height boxes in the properties panel to adjust it to the size that you want.

5.Click the Scene 1 button above the timeline to return to the main timeline.

6.Click the first frame in the timeline, open the Actions panel, and type in the following ActionScript code:

#include “tryItOut_snowStorm.as”

383

Chapter 16

7.Select File Save As, name the file tryItOut_snowStorm.fla, choose an appropriate directory, and save it.

8.Create a new script file by selecting File New and choosing ActionScript File from the New Document panel.

9.Select File Save As and ensure it is showing the same directory containing the Flash project file. Give the file the name tryItOut_snowStorm.as and save it.

10.Enter the following code into the new ActionScript file:

this.createEmptyMovieClip(“holderClip”, this.getNextHighestDepth()); holderClip.maxFlakes = 100;

holderClip.dropSpeed = 5;

var thisFlake:MovieClip;

for (var i:Number = 0; i < holderClip.maxFlakes; i++)

{

holderClip.attachMovie(“snowFlake”, “snowFlake” + i, ; holderClip.getNextHighestDepth());

thisFlake = holderClip[“snowFlake” + i]; thisFlake._x = randomRange(0, Stage.width); thisFlake._y = randomRange(0, Stage.height);

thisFlake._xscale = thisFlake._yscale = randomRange(50, 150); thisFlake._alpha = thisFlake._xscale - 50; thisFlake.cacheAsBitmap = true;

thisFlake.oscillationSeed = randomRange(0, 200);

}

holderClip.onEnterFrame = function()

{

var thisFlake:MovieClip;

for (var i:Number = 0; i < this.maxFlakes; i++)

{

thisFlake = this[“snowFlake” + i];

thisFlake._y += thisFlake._xscale * (this.dropSpeed / 100); thisFlake._x += Math.sin((thisFlake._y + ;

thisFlake.oscillationSeed) / 50);

if (thisFlake._y >= Stage.height)

{

thisFlake._x = randomRange(0, Stage.width); thisFlake._y = 0;

}

}

}

function randomRange(min:Number, max:Number)

{

return Math.random() * (max - min) + min;

}

11.Select File Save As, name the file tryItOut_onEnterFrame.fla, choose an appropriate directory, and save it. Select Control Test Movie.

384

Using ActionScript for Animation

How It Works

The first line creates a holder clip for the animation:

this.createEmptyMovieClip(“holderClip”, this.getNextHighestDepth());

As previously mentioned, this is a good practice for making animations more self-contained and easier to work with. It also gives you a clip to which you can attach the onEnterFrame handler.

A couple of variables are saved as properties in the container movie clip (this is preferred over creating timeline variables because the scope of the variables stays within the movie clip):

holderClip.maxFlakes = 100; holderClip.dropSpeed = 5;

The movie clips are created within the for loop. The first thing that the loop does is to attach the movie clip from the library to the container movie clip. The getNextHighestDepth() method ensures that each snowflake rests on its own layer:

holderClip.attachMovie(“snowFlake”, “snowFlake” + i, ; holderClip.getNextHighestDepth());

A temporary variable keeps a handle to the movie clip for convenience. This is also a performance aid, because local variable access is faster than associative array access. The temporary variable is declared outside the loop, also for performance reasons:

thisFlake = holderClip[“snowFlake” + i];

The x and y coordinates for each snowflake are initialized based on a random selection using the dimensions of the stage as the bounds for picking the values:

thisFlake._x = randomRange(0, Stage.width); thisFlake._y = randomRange(0, Stage.height);

Each snowflake is scaled so that they are not all a uniform size. The scaling ranges between 50% and 150% of the original size. The code simply assigns the result of the randomRange() function first to thisFlake._yscale and then to thisFlake._xscale all in one line:

thisFlake._xscale = thisFlake._yscale = randomRange(50, 150);

The transparency of each flake is adjusted according to the size of the flake. The principle here is that bigger flakes are closer to the viewer and should be more opaque, whereas smaller flakes are further away and should be harder to see:

thisFlake._alpha = thisFlake._xscale - 50;

The cacheAsBitmap option is a performance addition in Flash 8:

thisFlake.cacheAsBitmap = true;

It tells Flash that each of these movie clips being animated contains static content. Flash will use a cached bitmap version of the clip instead of rendering each clip each time. (The cacheAsBitmap property was introduced in Chapter 7.)

385

Chapter 16

The last step within the movie clip creation loop is to assign the movie clip a seed value that helps make the swishing back and forth of the flakes seem more random:

thisFlake.oscillationSeed = randomRange(0, 200);

It offsets the back-and-forth cycle so that they do not all move left and right in unison.

Now take a look at the contents of the onEnterFrame handler. Every time the event is generated, it loops through each of the movie clips. It knows how many clips there are because you saved numFlakes as a property of the container movie clip. Once again, you save the handle to the movie clip currently being manipulated to a temporary variable, both for readability and for performance:

var thisFlake:MovieClip;

for (var i:Number = 0; i < this.maxFlakes; i++)

{

thisFlake = this[“snowFlake” + i]; // ...

}

Because this loop is being called constantly, anything that improves (or degrades) performance has maximum effect within the loop.

Next in the loop, the y position is modified:

thisFlake._y += thisFlake._xscale * (this.dropSpeed / 100);

Rather than incrementing it by a constant value like in earlier examples, the increment depends on the size of the snowflake. Larger snowflakes are perceived as closer, and should fall faster to maintain that perception.

Some back-and-forth motion is introduced into the snowflake:

thisFlake._x += Math.sin((thisFlake._y + thisFlake.oscillationSeed) / 50);

Math.sin() is a convenient method for this because it produces output that smoothly oscillates between –1 and 1 as the input value continues to increase. The oscillation seed is used here to offset the oscillations so that each snowflake does not move back and forth at the same time.

When each snowflake reaches the bottom of the screen, it is placed back at the top at a new random x position:

if (thisFlake._y >= Stage.height)

{

thisFlake._x = randomRange(0, Stage.width); thisFlake._y = 0;

}

386

Using ActionScript for Animation

The randomRange() function enables you to quickly and easily pick randomly from any range of numbers:

function randomRange(min:Number, max:Number)

{

return Math.random() * (max - min) + min;

}

Now take a look at the concepts of easing and acceleration.

Introducing Easing and Acceleration

Moving things in a constant linear fashion is a relatively straightforward task, but how about moving things about in a more random manner, and adding some acceleration and deceleration into the mix? These tasks are actually easy to achieve and do not require as much math as you might think.

To apply easing to a moving movie clip means to make the transition gentler between at rest and in motion. It involves a more gradual slow-down or speed-up of the movie clip, and it tends to make transitions appear more natural. Easing can also be thought of the physics concepts of acceleration and deceleration. Easing-in corresponds with the concept of acceleration and easing-out corresponds with the concept of deceleration.

Easing Out

First look at the process of easing-out, or deceleration. Figure 16-5 shows what this motion looks like.

Starting position

Ending position

Figure 16-5

Fortunately, the math behind this is very simple. For every animation pass, you move the movie clip some fraction of the distance from its current location to the target position. Figure 16-6 shows this behavior visually, where each time the movie clip is moved one third of the distance separating itself and its stop point.

387