Easing

One thing I want to clear up right off the bat is that there is more than one type of easing. Even in the Flash IDE, while youre making a motion tween, you have the ability to ease in or ease out. The type of easing I will be discussing here is the same as the ease in of a motion tween. A bit later in this chapter, in the Advanced easing section, Ill provide you with a link where you can find out how to do all kinds of easing.

Simple easing

Simple easing is a very basic concept. You have something over here and you want to move it over there. Since youre creating the illusion of motion, you want to move it there gradually, over several frames . You could simply find the angle between the two, set a speed, use some trigonometry to work out the vx and vy , and set it in motion. Then you could check the distance to the target on each frame (using the Pythagorean Theorem, as described in Chapter 3), and when it was there, stop it. That approach might actually be adequate in some situations, but if youre trying to make something look like its moving naturally, it wont do.

The problem is that your object would move along at a fixed velocity, reach its target, and stop dead. If youre talking about some object moving along and hitting a brick wall, yes, it might be sort of like that. But when youre moving an object to a target , this generally implies that someone or something knows where this target is, and is moving something into place there deliberately. In such a case, the motion will start out fairly fast, and then slow down as it gets closer to the target. In other words, its velocity is going to be proportional to the distance to the target.

Lets take an example. Youre driving home. When you are a few miles away, youre going to be traveling as fast as the speed limit allows you (OK, maybe even fastermaybe even fast enough to earn yourself a ticket). When you pull off the highway and into your neighborhood, youll be going a bit slower. Once youre on your own street, a block or two away, youll be going far slower. As you approach your driveway , youre down to a few miles per hour . When you reach the last few feet of the driveway, youre moving a lot slower than when you pulled into the driveway. And inches before you stop, youre moving at a fraction of that speed.

If you take the time to look, youll see this behavior manifests itself even in small things like closing a drawer or door. You start out fast and gradually slow down. The next time you go to close a door, make an effort to follow through with the same speed you started with. Just be prepared to explain to anyone nearby why youre slamming doors.

So, when you use easing to move an object into position, it automatically takes on a very natural appearance. One of the coolest things is that simple easing is actually very easy to do. In fact, its probably easier than figuring out the angle, the vx , and the vy , and moving at a fixed speed.

Here is the strategy for easing:

  1. Decide on a number for your proportional motion. This will be a fraction of 1.

  2. Determine your target.

  3. Calculate the distance from the object to the target.

  4. Multiply the distance by the fraction. This is your velocity.

  5. Add the velocity value to the current position.

  6. Repeat steps 3 through 5 until the object is at the target.

Figure 8-1 illustrates the concept.

image from book
Figure 8-1: Basic easing

Lets go through these steps one at a time, and see how each looks in ActionScript. Dont worry about where to put the code yet. Im just showing you what the code looks like and what it means.

First, decide on a fraction to represent the proportion. As I said, the velocity will be proportional to the motion. Specifically, this means that the velocity will be a fraction of the distance, something between 0 and 1. The closer it is to 1, the quicker the object will move. The closer it is to 0, the slower it will move, but be careful, because too low a value will prevent the object from reaching the target at all. For starters, choose something like 0.2. Im going to call this variable easing . So you can start off with the following code:

 var easing:Number = 0.2; 

Next, determine your target. This is a simple x, y position. You can make it center stage for lack of anything better.

 var targetX:Number = Stage.width / 2; var targetY:Number = Stage.height / 2; 

Then calculate the distance to the target. Assuming you have a movie clip named ball , you just subtract the balls x and y from the target x and y.

 var dx:Number = targetX - ball._x; var dy:Number = targetY - ball._y; 

Your velocity is then the distance times the fraction:

 vx = dx * easing; vy = dy * easing; 

And you know what to do from there:

 ball._x += vx; ball._y += vy; 

Steps 3 to 5 need to be repeated, so those will go in your enterFrame function. Lets take a closer look at those three steps, as they can be largely simplified.

 var dx:Number = targetX - ball._x; var dy:Number = targetY - ball._y; vx = dx * easing; vy = dy * easing; ball._x += vx; ball._y += vy; 

You can condense the first two lines into the second two pretty easily:

 vx = (targetX - ball._x) * easing; vy = (targetY - ball._y) * easing; ball._x += vx; ball._y += vy; 

Or, if youre into the whole brevity thing, you can shrink it even further:

 ball._x += (targetX - ball._x) * easing; ball._y += (targetY - ball._y) * easing; 

The first few times you do easing, you might want to go with one of the more verbose syntaxes to make it clearer. But once youve done it a few hundred times, the third version communicates perfectly . Ill stick with the second version here, just to reinforce the idea that youre dealing with velocity.

Now, lets see it in action. You can start out with the same base file youve been using throughout the book. It just needs to contain a movie clip symbol named ball . Place an instance of the ball on stage, and then add the following code on frame 1 (found in ch08_01.fla ):

 var easing:Number = 0.2; var targetX:Number = Stage.width / 2; var targetY:Number = Stage.height / 2; onEnterFrame = function () {       var vx:Number = (targetX - ball._x) * easing;       var vy:Number = (targetY - ball._y) * easing;       ball._x += vx;       ball._y += vy; }; 

Make sure that the ball is originally placed far from the center, so you can see it moving. Play around with the easing variable to see how it affects the resulting motion.

The next thing you might want to do is make the ball draggable so you can move it around and see how it always goes back to its target. This is pretty similar to the drag-and-drop technique you set up in Chapter 7. Heres the code ( ch08_02.fla ):

 var easing:Number = 0.2; var targetX:Number = Stage.width / 2; var targetY:Number = Stage.height / 2;  var dragging:Boolean = false;   ball.onPress = function()   {   dragging = true;   this.startDrag();   }   ball.onRelease = ball.onReleaseOutside = function()   {   dragging = false;   this.stopDrag();   }  onEnterFrame = function () {  if(!dragging)   {  var vx:Number = (targetX - ball._x) * easing;             var vy:Number = (targetY - ball._y) * easing;             ball._x += vx;             ball._y += vy;  }  }; 

When to stop easing

If you are doing simple easing to a single target, eventually youll get to the point where the object is at the target and the purpose of the easing has been achieved. But, in the examples so far, the easing code continues to execute, even though the object isnt visibly moving anymore. This is a waste of CPU resources. If youve reached your goal, you might as well stop trying. At first glance, this would be as simple as checking if the object is at its target and turning off the enterFrame code, like so:

 if(ball._x == targetX && ball._y == targetY) {     // code to stop the easing } 

But it winds up being a little more tricky.

The type of easing we are discussing involves something known as Xenos Paradox. Xeno was yet another Greek guy who liked to measure things. Xeno tried to break down motion as follows : In order for something to move from point A to point B, it first must move to a point halfway between the two. Then it needs to travel from that point to a point halfway between there and point B. And then halfway again. Since you always need to move halfway to the target, you can never actually reach the target.

The paradox is that this sounds logical, but obviously, we do move from one point to another every day, so theres something wrong there. Lets take a look at it in Flash. On the x axis, a movie clip is at position 0. Say you want to move it to 100 on the x axis. To fit into the paradox, make the easing variable 0.5, so it always moves half the distance to the target. It progresses like this:

  • Starting at 0, after frame 1, it will be at 50.

  • Frame 2 will bring it to 75.

  • Now the distance is 25. Half of that is 12.5, so the new position will be 87.5.

  • Following the sequence, the position will be 93.75, 96.875, 98.4375, and so on. After 20 frames, it will be 99.999809265.

As you can see, it gets closer and closer, but never actually reaches the target, theoretically. However, things are a bit different when you examine what the code does. It comes down to the question, How small can you slice a pixel? The answer is 20. In fact, theres a name for a twentieth of a pixel: a twip . Internally, Flash calculates anything that uses pixels with twips. This includes positions of movie clips. Thus, if you trace the position of a movie clip, you might notice that it is always in multiples of 0.05.

In the example here, the closest a movie clip can get to 100 without actually getting there is 99.95. When you try to split the difference at that point, youre trying to add on (100 ˆ 99.95) / 2. This comes out to 0.025, or a fortieth of a pixel. But a twip is as low as you can go. You cant add half a twip, so you wind up adding 0. If you dont believe me, try the following code with a movie clip instance named ball on stage:

 var targ:Number = 100; ball._x = 0; for(var i:Number=0;i<20;i++) {       trace(i + ": " + ball._x);       ball._x += (targ - ball._x) * .5; } 

This just loops through 20 times, moving the ball half the distance to the target. Its basic easing code. I threw it in a for loop because I was only interested in tracing the positions, not actually seeing the motion. What youll find is that by the eleventh iteration, the ball has reached 99.95, and thats as far as it gets.

In tracing positions, you might also notice that occasionally you get a num ber like 96.85000000000001. This has to do with the way fractions are stored in a binary format, and has nothing to do with pixels, twips, or Flash itself. For more information, do a web search for binary round-off errors.

To make a long story short, no, your movie clip object is not going to get closer and closer, but yes, your movie clip might never reach its target. So, if youre doing a simple comparison, as in the previous example, your easing code will never get shut off. What you need to do is answer the question, When is it close enough? This comes down to determining if the distance to the target is less than a certain amount. For many applications, Ive found that if an object is within a pixel of its target, its safe to say it has arrived, and I can shut off easing.

If you are dealing with two dimensions, you can calculate the distance using the formula I introduced in Chapter 3:

 distance = Math.sqrt(dx * dx + dy * dy). 

If you are dealing with a single value for distance, as when you are moving an object on a single axis, you need to use the absolute value of that distance, as it may be negative. You can do this by using the Math.abs method.

OK, Ive done way too much talking. Lets see it in some code. Heres a simple program to demonstrate turning off easing ( ch08_03.fla ):

 var easing:Number = 0.2; var targ:Number = Stage.width / 2; onEnterFrame = ease; function ease() {       var dx:Number = targ - ball._x;       if(Math.abs(dx) < 1)       {             ball._x = targ;             delete onEnterFrame;             trace("done");       }       else       {             var vx:Number = dx * easing;             ball._x += vx;       } }; 

As you can see, this example expands the easing formula a bit to first calculate the distance, since youll need this to see if easing should be stopped . Perhaps now you can see why you need to use the absolute value of dx . If the ball were to the right of the target, dx would wind up as a negative number, the statement if(dx < 1) would evaluate as true, and that would be the end of things. By using Math.abs , you make sure that the actual distance is less than 1. You then place the ball where it is trying to go and disable the motion code.

Remember that if you are doing something like a drag-and-drop with easing, youll want to reenable the motion code when the ball is dropped. Why dont you go ahead and see if you can figure out that one for yourself. Ill give you a small hint: You want to reset onEnterFrame to equal move .

A moving target

In the examples so far, the target point has been a single, fixed location, but thats not a requirement. The distance is calculated on each frame, and the velocity is then calculated based on that. Flash doesnt care whether or not it reaches the target, or if the target keeps moving. It just happily goes on saying, Wheres my target? Whats the distance? Whats my velocity? on each and every frame.

You can easily make the mouse an easing target. Just plug the mouse coordinates in where you had targetX and targetY before. Heres a simpler version that does just that ( ch08_04.fla ):

 var easing:Number = 0.1; onEnterFrame = function () {       var dx:Number = _xmouse - ball._x;       var dy:Number = _ymouse - ball._y;       ball._x += dx * easing;       ball._y += dy * easing; }; 

Move the mouse around and see how the ball follows, and how it goes faster when you get further away.

Think of what other moving targets you could have. Maybe a movie clip could ease to another movie clip. Back in the early days of Flash, mouse trailers a trail of movie clips that followed the mouse aroundwere all the rage. Easing was one way of doing this. The first clip eased to the mouse, the second clip eased to the first, the third to the second, and so on. Go ahead and try it out (but if you put it on a live website, Ill deny any responsibility).

Easing isnt just for motion

If there is one point I want to get across in this book, its that the examples I give are simply that: examples. In each case, Im mainly just manipulating numbers that are used for various movie clip properties. For the most part, Im using the _x and _y properties to control positions of movie clips. Just remember that movie clips have a bunch of other properties that you can manipulate, and most of them are represented by numbers. So when you read a particular example, definitely try it out, but dont leave it at that. Try the same example on other properties. Here, Ill give you a few ideas to get you started.

Transparency

Apply easing to the _alpha property of a clip. Start out by setting it to 0, and making the target 100:

 ball._alpha = 0; var targetAlpha:Number = 100; 

Then you can fade it in with easing in an enterFrame handler:

 ball._alpha += (targetAlpha  ball._alpha) * easing; 

Or reverse the 0 and 100 to make it fade out.

Rotation

Set the _rotation property and a target rotation. Of course, you need something that can be visibly rotated , like an arrow:

 arrow._rotation = 90; var targetRotation:Number = 270; 

And then ease it:

 arrow._rotation += (targetRotation  arrow._rotation) * easing; 

Colors

If you are up for a real challenge, try easing on 24-bit colors. Youll need to start with red, green, and blue initial values and target values, perform the easing on each separate component color, and then combine them into a 24-bit color . For instance, you could ease from red to blue. Start with the initial and target colors:

 red = 255; green = 0; blue = 0; redTarget = 0; greenTarget = 0; blueTarget = 255; 

Then in your enterFrame handler, perform easing on each one. Here is just the red value:

 red += (redTarget  red) * easing; 

Then combine the three into a single value (as described in Chapter 4):

 col = red << 16  green << 8  blue; 

And use that for setRGB , or for a line, a fill color, or another element.

Advanced easing

Now that youve seen how simple easing works, you might consider using more complex easing formulas for additional effects. For instance, you might want something to start slowly, build up speed, and then slow down as it approaches its target. Or you might want to ease something into position over a certain time period or number of frames.

Robert Penner has become famous for collecting a lot of formulas, cataloging them, and implementing them in ActionScript. You can find his easing formulas at www.robertpenner.com.

OK, lets move on to perhaps my most favorite subject in Flash: springing.



Foundation ActionScript. Animation. Making Things Move
Foundation Actionscript 3.0 Animation: Making Things Move!
ISBN: 1590597915
EAN: 2147483647
Year: 2005
Pages: 137
Authors: Keith Peters

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net