成比例运动
缓动(ease)与弹性(spring)联系紧密。这两种方法都是将对象(通常指 Sprite 或
MovieClip)从某一点移动到目标点。使用缓动运动(Easing),如同让影片滑动到目标并停
止。使用弹性运动(Springing),会产生向前或向后的反弹,最终停止在目标点位。两种方
法具有一些共同点:
■ 需要一个目标点;
■ 确定到目标点的距离;
■ 成比例地将影片移动到目标点——距离越远,移动速度越快。
缓动运动(easing)与弹性运动(springing)的不同之处在于移动的比例。缓动运动时,
速度与距离成正比,离目标越远,物体运动速度越快。当物体与目标点非常非常接近时,就
几乎不动了。
弹性运动时,加速度与距离成正比。如果物体与目标离得很远,再用上加速度,会使移
动速度非常快。当物体接近目标时,加速度会减小,但依然存在!物体会飞过目标点,随后
再由反向加速度将它拉回来。最终,用摩擦力使其静止。
下面,我们分别看一下这两种方法,先从缓动(easing)开始。
缓动(Easing)
首先说明缓动的种类不只有一种。在 Flash IDE 中,制作补间动画时,我们就可以看
到 “缓动输入”(ease in) 和 “缓动输出”(ease out)。下面所讨论的缓动类型与运
动补间的 “缓动输出”相似。在本章后面的 “高级缓动”一节,将会给大家一个网站连接,
在那里可以学习制作所有缓动的效果。
简单缓动
简单缓动是个非常基础概念,就是将一个物体移到别处去。创建这个“运动效果”时,
希望物体能在几帧内慢慢移动到某一点。我们可以求出两点之间的夹角,然后设置速度,再
使用三角学计算出 vx 和 vy,然后让物体运动。每一帧都判断一下物体与目标点的距离,
如果到达了目标则停止。这种运动还需要一定条件的约束才能实现,但如果要让物体运动得
很自然,显然这种方法是行不通的。
问题在于物体沿着固定的速度和方向运动,到达目标点后,立即停止。这种方法,用于
表现物体撞墙的情景,也许比较合适。但是物体移动到目标点的过程,就像是某个人明确地
知道他的目的地,然后向着目标有计划地前进,起初运动的速度很快,而临近目标点时,速
度就开始慢下来了。换句话讲,它的速度向量与目标点的距离是成比例的。
先来举个例子。比如说我们开车回家,当离家还有几千米的距离时,要全速前进,当离
开马路开进小区时速度就要稍微慢一点儿。当还差两座楼时就要更慢一点儿。在进入车库时,
速度也许只有几迈。当进入停车位时速度还要更慢些,在还有几英尺的时候,速度几乎为零。
如果大家注意观察就会发现,这种行为就像关门、推抽屉一样。开始的速度很快,然后
逐渐慢下来。
在我们使用缓动使物体归位时, 运动显得很自然。简单的缓动运动实现起来也非常简单,
比求出夹角,计算 vx,vy 还要简单。下面是缓动的实现策略:
1. 确定一个数字作为运动比例系数,这是个小于 1 的分数;
2. 确定目标点;
3. 计算物体与目标点的距离;
4. 用距离乘以比例系数,得出速度向量;
5. 将速度向量加到当前物体坐标上;
6. 重复 3 到 5 步。
我们先来解释一下这个过程,看看在 ActionScript 中是怎样实现的。
首先,确定一个分数作为比例系数。我们说过,速度与距离是成比例的。也就是说速度
是距离的一部分。比例系数在 0 和 1 之间,系数越接近 1,运动速度就会越快;系数越接
近 0,运动速度就会越慢。但是要小心,系数过小会使物体无法到达目标。开始我们以 0.2
作为系数,这个变量名就叫 easing。初始代码如下:
var easing:Number = 0.2;
接下来,确定目标。只需要一个简单的 x,y 坐标,选择舞台中心坐标再合适不过了。
var targetX:Number = stage.stageWidth / 2;
var targetY:Number = stage.stageHeight / 2;
下面,确定物体到达目标的距离。假设已经有一个名为 ball 影片,只需要从 ball 的 x,y
坐标中减去目标的 x,y。
var dx:Number = targetX - ball.x;
var dy:Number = targetY - ball.y;
速度等于距离乘以比例系数:
vx = dx * easing;
vy = dy * easing;
129 130
下面,大家知道该怎么做了吧:
ball.x += vx;
ball.y += vy;
最后重复步骤 3 到步骤 5,因此只需加入 enterFrame 处理函数。
让我们再看一下这三个步骤,以便将它们最大程度地简化:
var dx:Number = targetX - ball.x;
var dy:Number = targetY - ball.y;
vx = dx * easing;
vy = dy * easing;
ball.x += vx;
ball.y += vy;
把前面四句简化为两句:
vx = (targetX - ball.x) * easing;
vy = (targetY - ball.y) * easing;
ball.x += vx;
ball.y += vy;
如果大家觉得还不够精简,还可以进一步缩短:
ball.x += (targetX - ball.x) * easing;
ball.y += (targetY - ball.y) * easing;
在开始学习使用缓动时,也许大家会比较喜欢用详细的句型,让程序看上去更加清晰。
但是当你使过几百次后,就会更习惯用第三种写法。下面,我们选用第二种句型,以加强对
速度的理解。
现在就来看一下脚本动作,依然延用 Ball 类。以下是文档类 Easing1.as:
package {
import flash.display.Sprite;
import flash.events.Event;
public class Easing1 extends Sprite {
private var ball:Ball;
private var easing:Number=0.2;
private var targetX:Number=stage.stageWidth / 2;
private var targetY:Number=stage.stageHeight / 2;
public function Easing1() {
trace(targetX,targetY);
init();
}
private function init():void {
ball=new Ball ;
addChild(ball);
addEventListener(Event.ENTER_FRAME,onEnterFrame);
}
private function onEnterFrame(event:Event):void {
var vx:Number=(targetX - ball.x) * easing;
var vy:Number=(targetY - ball.y) * easing; 131
ball.x+= vx;
ball.y+= vy;
}
}
}
试改变 easing 的值,观察运动效果。