Recipe 11.3.
Easing
Problem
You
want an object to smoothly
move to a specific location, slow down, and stop as it reaches that
spot.
Solution
Use an easing formula.
Discussion
First, we'll look at the concept of simple
easing. You have an object at a
certain position and you want it to ease to another position. Take
the distance between the two points and move the object a fraction
of that distancemaybe one-half, one-third, or less. On the next
iteration, find the new distance and move the object a fraction of
that. Continue this way until the object is so close to the target
that you can consider it there.
You'll see that the first couple of jumps are
quite big, but successive jumps get smaller and smaller until the
object appears not to be moving at all. Viewed in terms of
velocity, the velocity starts out high and approaches zero. Another
way of looking at it is that velocity is dependent on distance. A
large distance makes for a high velocity.
The following example shows a simple example of
easing. The target position is specified by _targetX and
_targetY. The fraction that the object moves each time is
set in _easingSpeed. Here it is set to 0.1, which means
the object moves one-tenth of the distance to the target on each
animation interval:
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Easing extends Sprite {
private var _sprite:Sprite;
private var _easingSpeed:Number = 0.1;
private var _targetX:Number = 400;
private var _targetY:Number = 200;
private var _timer:Timer;
public function Easing( ) {
_sprite = new Sprite( );
_sprite.graphics.beginFill(0x0000ff, 100);
_sprite.graphics.drawCircle(0, 0, 25);
_sprite.graphics.endFill( );
_sprite.x = 50;
_sprite.y = 50;
addChild(_sprite);
_timer = new Timer(30);
_timer.addEventListener("timer", onTimer);
_timer.start( );
}
public function onTimer(event:TimerEvent):void {
var vx:Number = (_targetX - _sprite.x) * _easingSpeed;
var vy:Number = (_targetY - _sprite.y) * _easingSpeed;
_sprite.x += vx;
_sprite.y += vy;
}
}
}
One problem with this setup is that the timer
continues to run, even after the object has gotten as close as it's
going to get to the target. To handle that, find the distance to
the target and if it is less than a certain value, just turn off
the timer, as illustrated by the bolded code in the following
example:
public function onTimer(event:TimerEvent):void {
var dx:Number = _targetX - _sprite.x;
var dy:Number = _targetY - _sprite.y;
var dist:Number = Math.sqrt(dx * dx + dy * dy);
if(dist < 1)
{
_sprite.x = _targetX;
_sprite.y = _targetY;
_timer.stop( );
}
else
{
var vx:Number = dx * _easingSpeed;
var vy:Number = dy * _easingSpeed;
_sprite.x += vx;
_sprite.y += vy;
}
}
This example first finds the distance on the two
axes and the total distance. If the distance is less than 1, it
places the object at the target point and kills the timer.
Otherwise, it continues as normal.
Sometimes though, you may not want the easing to
stop; for example, in a moving target. The following example has
the object easing toward the mouse. In other words, it simply
replaces mouseX and mouseY for _targetX
and _targetY:
public function onTimer(event:TimerEvent):void {
var vx:Number = (mouseX - _sprite.x) * _easingSpeed;
var vy:Number = (mouseY - _sprite.y) * _easingSpeed;
_sprite.x += vx;
_sprite.y += vy;
}
This is the simplest form of easing, and will
suffice in a good many cases. Robert Penner (http://www.robertpenner.com), a
well-known and highly respected Flash programmer, has developed a
set of much more complex easing formulas that have become a sort of
standard for easing applications. They even have been incorporated
into the standard ActionScript classes that come with both Flash
and Flex. At this writing, the equations are written for
ActionScript 1.0 and 2.0 only, but they could easily be adapted for
ActionScript 3.0. These equations do such things as easing in,
easing out, easing in and out, or
easing based on a specific time interval or number of frames, with
many different formulas.
See Also
Recipes 11.1
and 11.2
for the basics on velocity.
|