的起点。从这里开始内容也开始变得越来越有趣了,前面的章节都是些常用的概念与技术。
从今天开始,每章只着重介绍一两种特殊的运动。
两个名词术语,这章可以快速地略读。我会给出很多例子程序,可以使大家充分了解这项技
术的强大。
成比例运动
MovieClip)从某一点移动到目标点。使用缓动运动(Easing),如同让影片滑动到目标并停
止。使用弹性运动(Springing),会产生向前或向后的反弹,最终停止在目标点位。两种方
法具有一些共同点:
■ 需要一个目标点;
■ 确定到目标点的距离;
■ 成比例地将影片移动到目标点——距离越远,移动速度越快。
速度与距离成正比,离目标越远,物体运动速度越快。当物体与目标点非常非常接近时,就
几乎不动了。
动速度非常快。当物体接近目标时,加速度会减小,但依然存在!物体会飞过目标点,随后
再由反向加速度将它拉回来。最终,用摩擦力使其静止。
缓动(Easing)
到 “缓动输入”(ease in) 和 “缓动输出”(ease out)。下面所讨论的缓动类型与运
动补间的 “缓动输出”相似。在本章后面的 “高级缓动”一节,将会给大家一个网站连接,
在那里可以学习制作所有缓动的效果。
简单缓动
希望物体能在几帧内慢慢移动到某一点。我们可以求出两点之间的夹角,然后设置速度,再
使用三角学计算出 vx 和 vy,然后让物体运动。每一帧都判断一下物体与目标点的距离,
如果到达了目标则停止。 这种运动还需要一定条件的约束才能实现, 但如果要让物体运动得
很自然,显然这种方法是行不通的。
表现物体撞墙的情景,也许比较合适。但是物体移动到目标点的过程,就像是某个人明确地
知道他的目的地,然后向着目标有计划地前进,起初运动的速度很快,而临近目标点时,速
度就开始慢下来了。换句话讲,它的速度向量与目标点的距离是成比例的。
开马路开进小区时速度就要稍微慢一点儿。 当还差两座楼时就要更慢一点儿。在进入车库时,
速度也许只有几迈。 当进入停车位时速度还要更慢些,在还有几英尺的时候, 速度几乎为零。
逐渐慢下来。
比求出夹角,计算 vx,vy 还要简单。下面是缓动的实现策略:
1. 确定一个数字作为运动比例系数,这是个小于 1 的分数;
2. 确定目标点;
3. 计算物体与目标点的距离;
4. 用距离乘以比例系数,得出速度向量;
5. 将速度向量加到当前物体坐标上;
6. 重复 3 到 5 步。
是距离的一部分。比例系数在 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;
下面,大家知道该怎么做了吧:
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;
但是当你使过几百次后,就会更习惯用第三种写法。下面,我们选用第二种句型,以加强对
速度的理解。
package {
}
小球时开始拖拽,同时,删除 enterFrame 处理函数并且用 stage 侦听 mouseUp。在
mouseUp 函数中,停止拖拽,删除 mouseUp 方法,并重新开始 enterFrame。下面是文档类
Easin2.as :
package {
}
缓动何时停止
显示该对象,缓动代码仍在执行中,这一来浪费了 CPU 资源。当物体到达目标时,应该停
止执行代码。判断物体是否到达目标的方法非常简单,就像这样:
if(ball.x == targetX && ball.y == targetY) {
}
验。Xeno 将运动分解为下面几个步骤:物体要从 A 点到达 B 点,它首先要移动到两点间
一半的距离。然后物体再从该点出发,到达与 B 点距离一半的距离。然后再折半。每次只
移动离目标一半的距离,但永远无法准确地达到目标。
点,这样看来他的说法有些问题。到 Flash 中看看,影片在 x 轴上的位置为 0,假设要将
它移动到 x 轴为 100 的位置。按照悖论所说,设缓动系数为 0.5,这样每次运动到离目标
一半的距离。过程如下:
■ 从 0 点开始,经过 1 帧,到达 50。
■ 第 2 帧,到达 75。
■ 剩下的距离是 25。它的一半是 12.5 ,所以新的距离就是 87.5。
■ 按照这种顺序,位置将变化为 93.75, 96.875, 98.4375 等等。20 帧以后,将到达
99.999809265。
行试验时,结果就发生了一些微妙的变化。归根结底问题就在于“一次最少能移动多少个像
素”,答案是 1/20。事实上,二十分之一像素有个特有的名字:twip (缇)。在 Flash 内
部计算单位都采用 twip 像素,包括所有 Sprite 影片,影片剪辑和其它舞台对象。因此,
在显示影片位置时,这个数值永远是 0.05 的倍数。
99.5。再分隔的距离,就是加上 (100 – 99.95) /2。相当于加上了 0.025,四十分之一像
素。
素。如果大家不信的话,可以亲自试一下(提示:将代码放入框架类中的 init 方法):
var sprite:Sprite;
sprite = new Sprite();
addChild(sprite);
sprite.x = 0;
var targ:Number = 100;
for(var i:Number = 0; i
}
环,只是为了测试其位置,并不在于观察物体运动。循环到第 11 次时,影片已经到达了
99.95,这已经是它能够到达的最远的地方了。
来,缓动代码就永远不会停止。我们要回答的问题是 “哪里才是物体最接近的目标位置
这需要确定到目标点的距离是否小于某个范围。 我发现在很多软件中,
距离相差在一个像素以内,就可以说它已经到达了目标点,即可停止缓动了。
在处理二维坐标时,可以使用第三章所介绍的公式来计算点间距离:
distance = Math.sqrt(dx * dx + dy * dy)
可能是个负数,使用 Math.abs 方法。
(EasingOff.as):
package {
}
大家应该知道为什么要使用 dx 的绝对值了吧。如果小球在目标点的右边,dx 的值总是负
的,if (dx 际距离是否小于 1。
移动的目标
Flash 并不关心物体是否到达目标,或目标是否还在移动。它只会问 “我的目标在哪里br> 距离有多远度是多少,每帧都如此。因此,我们可以很容易将目标点改为鼠标所在
的位置,只需将原来 targetX 和 targetY 的地方,改成鼠标的坐标 (mouseX 和 mouseY)。
以下是一个比较简单的版本(EaseToMouse.as):
package {
}
的 Flash 时代,鼠标追踪者(mouse trailers)——即一串影片跟踪者鼠标的效果——曾
经风靡一时。缓动就是制作这种效果的方法之一。第一个影片缓动到鼠标上,第二个影片缓
动到第一个影片上,第三个再缓动到第二个上,依此类推。大家不妨一试。
缓动不仅限于运动
通常,使用 x,y 属性控制物体的位置。不过别忘了 Sprite 影片,影片剪辑以及各种显示
对象还有很多其它可以操作的属性,而且基本都是用数字表示的。所以在读例子程序时,也
应该试用其它属性代替这个例子中的属性。下面给大家一些启发。
透明度
将缓动用在 alpha 属性上。开始设置为 0 ,目标设置为 1 :
ball.alpha = 0;
var targetAlpha:Number = 1;
在 enterFrame 函数中,使用缓动可以实现影片淡入效果:
ball.alpha += (targetAlpha – ball.alpha) * easing;
若将 0 和 1 颠倒过来就可以实现影片的淡出效果。
旋转
比如一个箭头(arrow):
arrow.rotation = 90;
var targetRotation:Number = 270;
arrow.rotation += (targetRotation – arrow.rotation) * easing;
颜色
值,使用缓动单独表现每一色彩元素的值,然后将它们再组合成 24 位色彩值。例如,我们
可以从 red 缓动到 blue。初始颜色如下:
red = 255;
green = 0;
blue = 0;
redTarget = 0;
greenTarget = 0;
blueTarget = 255;
在 enterFrame 处理函数中的每一帧执行缓动。这里只表现一个 red 值:
red += (redTarget – red) * easing;
再将这三个数值组合为一个数(如第四章介绍的):
col = red 最后可以在 ColorTransform (见第四章),线条颜色或填充色中使用该颜色值。
高级缓动
的缓动公式制作一些效果。例如,在开始时比较缓慢,然后渐渐开始加速,最后在接近目标
时再将速度慢下来。或者希望在一段时间或若干帧内完成缓动效果。
www.robertpenner.com 中找到他的缓动公式。在他写这些内容时 AS 3 版本还没有出现,
但是用我们前面几章所学知识,将它们转化为 AS 3 版本的也是件非常容易的事。
弹性运动
念。几乎所有的物体都可以使用弹性运动。下面就来看看什么是弹性运动以及在 Flash 编
程中的应用。
实中弹簧的性质。把一个小球拴在橡皮圈一头,再将另一头系在一个固定的地方。当小球悬
在半空时,在没有施加外力的情况下,小球就处在目标点的位置上。再将小球微微拉动,松
手后橡皮圈会对其施加一些外力,又将小球拽回了目标点。如果用最大力量将小球挪远,那
么橡皮圈就会对小球施加很大的力。小球急速向目标点飞去,并朝着另一面运动。这时,小
球的速度非常快。 当它越过了目标点时,橡皮圈开始把它向回拉——改变其速度向量。这时,
小球会继续运动,但是它运动得越远,所受到的拉力就越大。然后,速度向量为零,方向相
反,一切再重新开始。 最终,在反弹了几次后,速度逐渐慢下来直到停止——停在目标点上。
进行实验。
一维坐标上的弹性运动
动到中心点的弹性。像使用缓动一样,需要一个变量保存弹性的数值。可以认为这个数同距
离的比例, 较大的弹性值会使弹性运动显得十分僵硬。较小的弹性值会使弹性运动像一条松
紧带。我们选用 0.1 作为弹性 (spring) :
private var spring:Number = 0.1;
private var targetX:Number = stage.stageWidth / 2;
private var vx:Number = 0;
不要担心物体当前的位置,只需要知道如何确定这些变量与表达式就可以了。
然后加入运动代码并且找出与目标点的距离:
var dx:Number = targetX – ball.x;
下面计算加速度。加速度与距离成正比,也就是距离乘以 spring 的值:
var ax:Number = dx * spring;
得到了加速度以后,我们就回到了熟悉的地方,把加速度加到速度向量中。
vx += ax;
ball.x += vx;
为 100,spring 值为 0.1。执行过程如下:
1. 距离(100) 乘以 spring,得到 10。将它加入 vx 中,此时 vx 变为 10。再将 vx 加入
到速度向量上使得 x 位置变为 10。
2. 下一次,距离(100-10) 等于 90。加速度为 90 乘以 0.1,结果为 9。将结果加入 vx ,
使 vx 变为 19。 x 坐标变为 29。
3. 下一次,距离为 71,加速度为 7.1,将结果加到 vx 中,使 vx 变成 26.1。 x 坐标变
为 55.1。
4. 下一次,距离为 44.9,加速度为 4.49, vx 变成 30.59。 x 坐标变为 85.69。
虽然涨幅不像启初那样快,但是速度却越来越快。
于 -17。将这一部分加入到速度向量中,会使物体的移动稍稍慢下来。
是有效的,使用下面这个文档类(Spring.as):
package {
}
述弹性运动时说过“速度逐渐慢下来直到停止”。由于小球每次摇摆时的距离相同,所以速
度向量也相同,这样它就会以同样的速度来回摆动。这时,我们需要引入摩擦力。非常简单
——只需要一个 friction 变量,值为 0.95。放在类开始的地方作为成员变量:
private var friction:Number = 0.95;
在 enterFrame 函数中,每次将 vx 乘以 friction,就可以了。
文档类 Spring2.as 的 onEnterFrame 方法如下:
private function onEnterFrame(event:Event):void {
}
效果。认真理解这个程序会对大家非常有帮助。掌握这个程序后,就来看看二维的弹性运动
吧。
二维弹性运动
package {
}
像一维的弹性运动。是的,虽然小球是沿着 x,y 轴运动,但它仍是直线运动。这是因为加
速度的起点均为零,并且两种力的大小相同,因此是直线运动到目标点。
真实了。但这只是个开始,更厉害的还在后面呢。
向移动目标运动
简便快捷的方法——小球跟随鼠标。要让小球跟随鼠标位置非常简单,只要将原来的
targetX 和 targetY 变成鼠标位置即可。在弹性运动中也是如此,每一帧都要计算物体与
目标点的距离,然后再确定加速度。
的程序做如下修改:
var dx:Number = targetX – ball.x;
var dy:Number = targetY – ball.y;
改为:
var dx:Number = mouseX – ball.x;
var dy:Number = mouseY – ball.y;
有什么问题。
弹簧在哪br>
要用绘图 API 绘制一条线即可!绘图指令可以直接写在 Sprite 的子类中。在很多复杂的
程序中,我们可能需要单独创建一个空影片当作绘图层来用。
置 lineStyle 并绘制出小球与鼠标的连线。我们只需要在 enterFrame 函数中执行如下操
作:
graphics.clear();
graphics.lineStyle(1);
graphics.moveTo(ball.x, ball.y);
graphics.lineTo(mouseX, mouseY);
简单,只需要在每帧的 vy 中加入重力(gravity)。以下代码结合了重力与画线指令
(Spring5.as):
package {
private function onEnterFrame(event:Event):void {
}
让小球下坠。如果重力太小的话,就看不到效果了。
常数,取决于物体所在星球的大小和质量。我们所能做的就是累加物体的质量,以便在物体
上产生多个重力。因此,严格来讲,重力还应该是 0.5,而质量应该在 10 左右。接下来,
用质量乘以重力等于 5。或者可将 gravity 变量名改为
forceThatGravityIsExerti
就可以节省一下空间使用变量名 gravity。
我们可以有无限多种数字的组合,可以建立出任何类型的重力系统。
文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91271 人正在系统学习中
来源:coding_most
声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!