打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Flash基础理论课 第八章 缓动与弹性运动Ⅱ

返回“Flash基础理论课 - 目录”

弹性运动

一直以来,我都认为弹性运动将是ActionScript. 动画中最强大和最有用的物理学概念。几乎所有的物体都可以使用弹性运动。下面就来看看什么是弹性运动以及在Flash 编程中的应用。

如同本章开始时所提到的,弹性的加速度与物体到目标点的距离成正比例。想象一下现实中弹簧的性质。把一个小球拴在橡皮圈一头,再将另一头系在一个固定的地方。当小球悬在半空时,在没有施加外力的情况下,小球就处在目标点的位置上。再将小球微微拉动,松手后橡皮圈会对其施加一些外力,又将小球拽回了目标点。如果用最大力量将小球挪远,那么橡皮圈就会对小球施加很大的力。小球急速向目标点飞去,并朝着另一面运动。这时,小球的速度非常快。当它越过了目标点时,橡皮圈开始把它向回拉——改变其速度向量。这时,小球会继续运动,但是它运动得越远,所受到的拉力就越大。然后,速度向量为零,方向相反,一切再重新开始。最终,在反弹了几次后,速度逐渐慢下来直到停止——停在目标点上。

下面我们将这个过程翻译成 ActionScript。为了简化这个过程,我们先在一维坐标上进行实验。

一维坐标上的弹性运动

这里我们仍然使用可以拖拽的小球作为主体。默认位置还是x轴的0 点,使它具有运动到中心点的弹性。像使用缓动一样,需要一个变量保存弹性的数值。可以认为这个数同距离的比例,较大的弹性值会使弹性运动显得十分僵硬。较小的弹性值会使弹性运动像一条松紧带。我们选用 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;

在写代码前,先来模拟一下运行时的数据。假设物体的x坐标为0,vx为0,目标x为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。

注意,每次的加速度随着物体越接近目标,变得越来越小,但是速度向量仍在不断增涨。虽然涨幅不像启初那样快,但是速度却越来越快。

几次过后,物体就超过了目标点,到达了117的位置。现在的距离是100 – 117,等于-17。将这一部分加入到速度向量中,会使物体的移动稍稍慢下来。

现在大家知道弹性是如何工作了吧,让我们来实践一下。与往常一样,要保证 Ball 类是有效的,使用下面这个文档类(Spring.as):

package {
 import flash.display.Sprite;
 import flash.events.Event;
 public class Spring1 extends Sprite {
  private var ball:Ball;
  private var spring:Number = 0.1;
  private var targetX:Number = stage.stageWidth / 2;
  private var vx:Number = 0;
  public function Spring1() {
   init();
  }
  private function init():void {
   ball = new Ball();
   addChild(ball);
   ball.y = stage.stageHeight / 2;
   addEventListener(Event.ENTER_FRAME, onEnterFrame);
  }
  private function onEnterFrame(event:Event):void {
   var dx:Number = targetX - ball.x;
   var ax:Number = dx * spring;
   vx += ax;
   ball.x += vx;
  }
 }
}

试验一下,可以看出一个类似于弹簧的效果,唯一的问题是它永远不会停止。前面在描述弹性运动时说过“速度逐渐慢下来直到停止”。由于小球每次摇摆时的距离相同,所以速度向量也相同,这样它就会以同样的速度来回摆动。这时,我们需要引入摩擦力。非常简单——只需要一个 friction变量,值为0.95。放在类开始的地方作为成员变量:

private var friction:Number = 0.95;

在enterFrame. 函数中,每次将vx 乘以 friction,就可以了。

文档类 Spring2.as的onEnterFrame. 方法如下:

private function onEnterFrame(event:Event):void {
    var dx:Number = targetX - ball.x;
    var ax:Number = dx * spring;
    vx += ax;
    vx *= friction;
    ball.x += vx;
}

这样一来,程序就完整了,虽说只是个一维的弹性运动。试改变friction的值观察运动效果。认真理解这个程序会对大家非常有帮助。掌握这个程序后,就来看看二维的弹性运动吧。

二维弹性运动

好了,不用麻烦了,直接看程序(Spring3.as):

package {
 import flash.display.Sprite;
 import flash.events.Event;
 public class Spring3 extends Sprite {
  private var ball:Ball;
  private var spring:Number = 0.1;
  private var targetX:Number = stage.stageWidth / 2;
  private var targetY:Number = stage.stageHeight / 2;
  private var vx:Number = 0;
  private var vy:Number = 0;
  private var friction:Number = 0.95;
  public function Spring3() {
   init();
  }
  private function init():void {
   ball = new Ball();
   addChild(ball);
   addEventListener(Event.ENTER_FRAME, onEnterFrame);
  }
  private function onEnterFrame(event:Event):void {
   var dx:Number = targetX - ball.x;
   var dy:Number = targetY - ball.y;
   var ax:Number = dx * spring;
   var ay:Number = dy * spring;
   vx += ax;
   vy += ay;
   vx *= friction;
   vy *= friction;
   ball.x += vx;
   ball.y += vy;
  }
 }
}

我们看到,唯一不同之处就是加入了y轴的运动。但问题是,这个效果看上去还是很像一维的弹性运动。是的,虽然小球是沿着x,y轴运动,但它仍是直线运动。这是因为加速度的起点均为零,并且两种力的大小相同,因此是直线运动到目标点。

为了让效果更好,将初始 vx的值设置得大一些,比如 50。现在,看起来更加形象、真实了。但这只是个开始,更厉害的还在后面呢。

向移动目标运动

实现弹性运动并不需要目标点是固定。前面在介绍缓动运动时,我们就介绍了一个非常简便快捷的方法——小球跟随鼠标。要让小球跟随鼠标位置非常简单,只要将原来的targetX和targetY变成鼠标位置即可。在弹性运动中也是如此,每一帧都要计算物体与目标点的距离,然后再确定加速度。

效果非常 Cool,我认为值得大家多写几遍。事实上,代码的变化并不大,只需将前面的程序做如下修改:

var dx:Number = targetX - ball.x;
var dy:Number = targetY - ball.y;

改为:

var dx:Number = mouseX - ball.x;
var dy:Number = mouseY - ball.y;

设置完成后,就可以将targetX和targetY 这两个变量声明删除。如果不删,也不会有什么问题。

弹簧在哪?

下面我们将看到小球在橡皮圈上运动的情况。但是似乎还需要一个可见的橡皮圈,只需要用绘图 API 绘制一条线即可!绘图指令可以直接写在Sprite的子类中。在很多复杂的程序中,我们可能需要单独创建一个空影片当作绘图层来用。

方法很简单。在确定了小球的位置后,调用 clear() 将之前的线条擦除。然后重新设置 lineStyle. 并绘制出小球与鼠标的连线。我们只需要在enterFrame. 函数中执行如下操作:

graphics.clear();
graphics.lineStyle(1);
graphics.moveTo(ball.x, ball.y);
graphics.lineTo(mouseX, mouseY);

非常有趣!我们还能做什么?再加上重力怎么样?这样小球看上去更像是悬在空中。很简单,只需要在每帧的vy 中加入重力(gravity)。以下代码结合了重力与画线指令(Spring5.as):

package {
 import flash.display.Sprite;
 import flash.events.Event;
 public class Spring5 extends Sprite {
  private var ball:Ball;
  private var spring:Number = 0.1;
  private var vx:Number = 0;
  private var vy:Number = 0;
  private var friction:Number = 0.95;
  private var gravity:Number = 5;
  public function Spring5() {
   init();
  }
  private function init():void {
   ball = new Ball();
   addChild(ball);
   addEventListener(Event.ENTER_FRAME, onEnterFrame);
  }
  private function onEnterFrame(event:Event):void {
   var dx:Number = mouseX - ball.x;
   var dy:Number = mouseY - ball.y;
   var ax:Number = dx * spring;
   var ay:Number = dy * spring;
   vx += ax;
   vy += ay;
   vy += gravity;
   vx *= friction;
   vy *= friction;
   ball.x += vx;
   ball.y += vy;
   graphics.clear();
   graphics.lineStyle(1);
   graphics.moveTo(ball.x, ball.y);
   graphics.lineTo(mouseX, mouseY);
  }
 }
}

执行后的结果如图 8-2 所示。请注意,我们加入的重力 (gravity) 只有5,只是为了让小球下坠。如果重力太小的话,就看不到效果了。

图8-2 可见的鼠标弹簧

我们刚刚又违背了真实的物理学。当然,不能在物体上施加“累积重力”!重力是一个常数,取决于物体所在星球的大小和质量。我们所能做的就是累加物体的质量,以便在物体上产生多个重力。因此,严格来讲,重力还应该是0.5,而质量应该在10左右。接下来,用质量乘以重力等于5。或者可将gravity变量名改为forceThatGravityIsExertingOnThisObjectBasedOnItsMass。好了,大家明白这个意思后我就可以节省一下空间使用变量名 gravity。

同样,试验一下这个程序。试减少gravity与spring的值,试改变friction的值。我们可以有无限多种数字的组合,可以建立出任何类型的重力系统。

声明:该文章系网友上传分享,此内容仅代表网友个人经验或观点,不代表本网站立场和观点;若未进行原创声明,则表明该文章系转载自互联网;若该文章内容涉嫌侵权,请及时向上学吧网站投诉>>
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
动量守恒与能量守恒
as3 来回(上下)移动
AS3实现的弹性按钮效果——修订版(原创)
180行JavaScript代码实现的小球随机移动代码
AS3.0制作逼真的喷泉动画详细教程
html5弹跳球示例代码
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服