转 第八章 缓动与弹性运动(2)(as3.0)

AS3常用动画效果公式集合 AS3缓动公式: sprite.x += (targetX – sprite.x) * easing;//easing为缓动系数变量 sprite.y += (targetY – sprite.y) * easing; AG: <!-- 示例一:AS3缓动公式 从(0,0)移到(x,y) --> <div id="box" style="width: 100px; height: 100px; background: #f85455;position: absolute;"&gt 阅读详情

弹簧链
      下面我们将几个弹性小球串联起来。 在介绍缓动一节时,我们简单地讨论了鼠标跟随的
概念,意思是说一个物体跟随鼠标,另一个物体再跟随这个物体,依此类推。当时没有给大
家举例子,  是因为这个效果现在看来有些逊色。 但是,当我们在弹性运动中使用这个概念时,
效果就截然不同了。
      本程序的设计思想:创建三个小球,名为 ball0, ball1, ball2。 第一个小球,ball0 的
动作与上面例子中的效果是相同的。 ball1 向 ball0 运动,ball2 向 ball1 运动。每个
小球都受到重力的影响,所以它们都会向下坠。代码稍有些复杂,文档类 Chain.as:
package {
  import flash.display.Sprite;
  import flash.events.Event;
  public class Chain extends Sprite {
   private var ball0:Ball;
   private var ball1:Ball;
   private var ball2:Ball;
   private var spring:Number = 0.1;
   private var friction:Number = 0.8;
   private var gravity:Number = 5;
   public function Chain() {
     init();
   }
   private function init():void {
     ball0 = new Ball(20);
     addChild(ball0);
     ball1 = new Ball(20);
     addChild(ball1);
     ball2 = new Ball(20);
     addChild(ball2);
     addEventListener(Event.ENTER_FRAME, onEnterFrame);
   }
   private function onEnterFrame(event:Event):void {
     moveBall(ball0, mouseX, mouseY);
     moveBall(ball1, ball0.x, ball0.y);
     moveBall(ball2, ball1.x, ball1.y);
     graphics.clear();
     graphics.lineStyle(1);
     graphics.moveTo(mouseX, mouseY);
     graphics.lineTo(ball0.x, ball0.y);
     graphics.lineTo(ball1.x, ball1.y);
     graphics.lineTo(ball2.x, ball2.y);
   }
   private function moveBall(ball:Ball,targetX:Number,targetY:Number):void {
     ball.vx += (targetX - ball.x) * spring;
     ball.vy += (targetY - ball.y) * spring;
     ball.vy += gravity;
     ball.vx *= friction;
     ball.vy *= friction;
     ball.x += ball.vx;
     ball.y += ball.vy;
   }
  }
}
    看一下 Ball 这个类,我们发现每个对象实例都有自己 vx 和 vy 属性,并且它们的初
始值均为 0。所以在 init 方法中,我们只需要创建小球并把它们加入显示列表。
    然后在 onEnterFrame 函数中,实现弹性运动。这里我们调用了 moveBall 方法,比复
                          该函数的参数分别为一个 ball 对象以及目标点的 x,y 坐标。
制三次运动代码要好用得多。
每个小球都调用这个函数,第一个小球以鼠标的 x,y 作为目标位置,第二第三个小球以第
一第二个小球作为目标位置。
    最后,在确定了所有小球的位置后,开始画线,画线的起点是鼠标位置,然后依次画到
每个小球上,这样橡皮圈就连接上了所有的小球。注意,程序中的 friction 降为 0.8 为
了使小球能够很快稳定下来。
创建一个数组保存链中所有对象的引用,然后通过循环遍历数组中的每个小球并执行运动,
使这个程序更加灵活。这里只需要做一些小小的改变。首先,需要两个新的变量代表数组和
对象数目:
private var balls:Array;
private var numBalls:Number = 5;
在函数 init 中,使用 for 循环创建所有对象,并将对象引用加入数组:
private function init():void {
balls = new Array();
    for(var i:uint = 0; i < numBalls; i++) {
        var ball:Ball = new Ball(20);
        addChild(ball);
        balls.push(ball);
    }
    addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
    最后,onEnterFrame 方法的变化最大。首先设置线条,将绘图起点移动到鼠标位置,
再到第一个小球,然后循环为剩下的小球设置位置并连线。通过改变 numBalls 变量,我们
可以加入任意多个小球。
private function onEnterFrame(event:Event):void {
    graphics.clear();
    graphics.lineStyle(1);
    graphics.moveTo(mouseX, mouseY);
    moveBall(balls[0], mouseX, mouseY);
    graphics.lineTo(balls[0].x, balls[0].y);
    for(var i:uint = 1; i < numBalls; i++) {
        var ballA:Ball = balls[i-1];
        var ballB:Ball = balls[i];
        moveBall(ballB, ballA.x, ballA.y);
        graphics.lineTo(ballB.x, ballB.y);
    }
}
多目标点弹性运动
    我们在第五章讨论速度与加速度时,曾说过如何使一个物体受到多种外力。如果每种力
都是加速度,我们只需要把它们一个个都加到速度向量中去。因为弹力不过就是施加在物体
上的一种加速度,因此在一个物体上添加多种弹力也是非常容易的。
    下面是创建多目标弹簧的方法:我们需要三个控制点,这些点都是 Ball 类的实例,并
且具有简单的拖拽功能,用它们作为小球弹性运动的控制点。小球会立即运动到点,并在两
点间寻找平衡。换句话讲,每个目标都会对小球施加一定的外力,小球的运动速度就是这些
外力相加的结果。
    例子程序相当复杂,使用多个方法处理不同的事件。以下是代码(文档类
MultiSpring.as),看过后再进行分段讲解:
package {
 import flash.display.Sprite;
 import flash.events.Event;
 import flash.events.MouseEvent;
 public class MultiSpring extends Sprite {
  private var ball:Ball;
  private var handles:Array;
  private var spring:Number = 0.1;
  private var friction:Number = 0.8;
  private var numHandles:Number = 3;
  public function MultiSpring() {
    init();
  }
  private function init():void {
    ball = new Ball(20);
    addChild(ball);
    handles = new Array();
    for (var i:uint = 0; i < numHandles; i++) {
     var handle:Ball = new Ball(10, 0x0000ff);
     handle.x = Math.random() * stage.stageWidth;
     handle.y = Math.random() * stage.stageHeight;
     handle.addEventListener(MouseEvent.MOUSE_DOWN, onPress);
     addChild(handle);
     handles.push(handle);
    }
    addEventListener(Event.ENTER_FRAME, onEnterFrame);
    addEventListener(MouseEvent.MOUSE_UP, onRelease);
  }
private function onEnterFrame(event:Event):void {
  for (var i:uint = 0; i < numHandles; i++) {
   var handle:Ball = handles[i] as Ball;
   var dx:Number = handle.x - ball.x;
   var dy:Number = handle.y - ball.y;
   ball.vx += dx * spring;
   ball.vy += dy * spring;
  }
  ball.vx *= friction;
  ball.vy *= friction;
  ball.x += ball.vx;
  ball.y += ball.vy;
  graphics.clear();
  graphics.lineStyle(1);
  for (i = 0; i < numHandles; i++) {
   graphics.moveTo(ball.x, ball.y);
   graphics.lineTo(handles[i].x, handles[i].y);
  }
}
private function onPress(event:MouseEvent):void {
  event.target.startDrag();
   }
   private function onRelease(event:MouseEvent):void {
     stopDrag();
   }
  }
}
      在 init 方法中,创建小球并用 for 循环创建三个控制点,随机安排位置,并为它们
设置拖拽行为。
      onEnterFrame 方法循环取出每个控制点,使小球向该点方向运动。然后,用控制点的
坐标设置小球的速度,反复循环,从小球开始向各个控制点画线。onPress 方法的内容非常
简单,但是请注意 onRelease 函数,我们无法知道当前拖拽的是哪个小球。幸运的是,使
用任何一个显示调用 stopDrag 方法,  都可以停止所有的拖拽,所以只需要在文档类中直接
调用该方法。
      我们只要改变 numHandles 变量的值,就可以轻松地设置控制点的数量。

    到目前为止,我相信大家已经有了很多的心得与体会,并且开始尝试解决一些书中没有
提到的问题。如果真是这样的话,那就太好了!这也正是我写这本书的目的。

 


目标偏移
    我们拿到一个真正的弹簧——有弹性的金属圈——然后将它的一头固定起来, 另一头放
上小球或其它物体,那么物体运动的目标点是哪里?难道说目标点是固定弹簧的那头儿?
不,这并不实际。小球永远也到不了这个点,因为它会受到弹簧自身的阻碍。一旦弹簧变回
了正常的长度,它会对小球施加更大的力。因此,目标点就应该是弹簧展开后的末端。
    要寻找目标点,首先要找到物体与固定点之间的夹角,然后沿这个角度从固定点向外展
开一段长度——弹簧的长度。换句话讲,如果弹簧长度是 50,小球与固定点的夹角是 45 度
的话,那么就要以 45 度的夹角向外运动 50 个像素,而这个点就是小球的目标点。图 8-5
解释了这一过程。


寻找目标点的代码如下:
var dx:Number = ball.x - fixedX;
var dy:Number = ball.y - fixedY;
var angle:Number = Math.atan2(dy, dx);
var targetX:Number = fixedX + Math.cos(angle) * springLength;
var targetY:Number = fixedY + Math.sin(angle) * springLength;
      运行结果是,物体向着固定点运动,但会在与目标点相差一段距离时停止移动。大家还
要注意,虽然我们叫它“固定点”,只是代表弹簧固定到的某个点。而不是指这个点不能移
动。也许最好的方法就是看代码。
      我们继续使用鼠标位置作为固定点,弹簧的长度为 100 像素。以下是文档类
(OffsetSpring.as):
package {
  import flash.display.Sprite;
  import flash.events.Event;
  public class OffsetSpring 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 springLength:Number = 100;
   public function OffsetSpring() {
     init();
   }
   private function init():void {
     ball = new Ball(20);
     addChild(ball);
     addEventListener(Event.ENTER_FRAME, onEnterFrame);
   }
   private function onEnterFrame(event:Event):void {
     var dx:Number = ball.x - mouseX;
                                                                                145
     var dy:Number = ball.y - mouseY;
     var angle:Number = Math.atan2(dy, dx);
     var targetX:Number = mouseX + Math.cos(angle) * springLength;
     var targetY:Number = mouseY + Math.sin(angle) * springLength;
     vx += (targetX - ball.x) * spring;
     vy += (targetY - ball.y) * spring;
     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);
   }
  }
}
      虽然我们能够看到运行结果,但却不能真正发现这项技术的特殊用处。没关系,下一节
会给大家一个特别的例子。


弹簧连接多个物体
    我们知道如何用弹簧连接两个物体,还知道这个点不是固定的。但是,如果另一个物体
上还有一个弹簧反作用在第一个物体上,又是怎样的呢?这里有两个物体之间由一根弹簧连
接。其中一个运动了,另一个物体就要向该物体移动过来。
    我开始认为制作这种效果会导致死循环从而无法实现,或者至少会引起错误。但我也没
管那么多,勇敢地进行尝试。结果非常完美!
    虽然前面已经描述了一些策略,但这里还要细致得说一下:物体 A 以物体 B 作为目标,
并向它移动。物体 B 反过来又以物体 A 作为目标。事实上,本例中目标偏移起了重要的作
用。如果一个物体以其它物体直接作为目标,那么它们之就会相互吸引,最终聚集在一个点
上。通过使用偏移目标,我们就可以使它们之间保持距离。
     下面举一个例子,我们需要两个 Ball 类的实例。分别为 ball0 和 ball1。ball0 向
ball1 偏移运动。ball1 向 ball0 偏移运动。为了不去反复写偏移弹性运动的代码,我们
将这些功能写到函数 springTo 中,直接调用函数即可。如果想让 ball0 向 ball1 运动,
只要写 springTo(ball0, ball1), 然后再让 ball1 向 ball0 运动,就写 springTo(ball1,
ball0)。 还要设置两个变量,ball0Dragging 和 ball1Dragging,作为每个小球运动的开关。
以下是文档类(DoubleSpring.as):
package {
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;
public class DoubleSpring extends Sprite {
 private var ball0:Ball;
 private var ball1:Ball;
 private var ball0Dragging:Boolean = false;
 private var ball1Dragging:Boolean = false;
 private var spring:Number = 0.1;
 private var friction:Number = 0.95;
 private var springLength:Number = 100;
 public function DoubleSpring() {
   init();
 }
 private function init():void {
   ball0 = new Ball(20);
   ball0.x = Math.random() * stage.stageWidth;
   ball0.y = Math.random() * stage.stageHeight;
   ball0.addEventListener(MouseEvent.MOUSE_DOWN, onPress);
   addChild(ball0);
   ball1 = new Ball(20);
   ball1.x = Math.random() * stage.stageWidth;
   ball1.y = Math.random() * stage.stageHeight;
   ball1.addEventListener(MouseEvent.MOUSE_DOWN, onPress);
   addChild(ball1);
   addEventListener(Event.ENTER_FRAME, onEnterFrame);
   stage.addEventListener(MouseEvent.MOUSE_UP, onRelease);
 }
 private function onEnterFrame(event:Event):void {
   if (!ball0Dragging) {
    springTo(ball0, ball1);
   }
   if (!ball1Dragging) {
    springTo(ball1, ball0);
  }
  graphics.clear();
  graphics.lineStyle(1);
  graphics.moveTo(ball0.x, ball0.y);
  graphics.lineTo(ball1.x, ball1.y);
}
private function springTo(ballA:Ball, ballB:Ball):void {
  var dx:Number = ballB.x - ballA.x;
  var dy:Number = ballB.y - ballA.y;
  var angle:Number = Math.atan2(dy, dx);
  var targetX:Number = ballB.x - Math.cos(angle) * springLength;
  var targetY:Number = ballB.y - Math.sin(angle) * springLength;
  ballA.vx += (targetX - ballA.x) * spring;
  ballA.vy += (targetY - ballA.y) * spring;
  ballA.vx *= friction;
  ballA.vy *= friction;
  ballA.x += ballA.vx;
  ballA.y += ballA.vy;
   }
   private function onPress(event:MouseEvent):void {
     event.target.startDrag();
     if (event.target == ball0) {
      ball0Dragging = true;
     }
     if (event.target == ball1) {
      ball1Dragging = true;
     }
   }
   private function onRelease(event:MouseEvent):void {
     ball0.stopDrag();
     ball1.stopDrag();
     ball0Dragging = false;
     ball1Dragging = false;
   }
  }
}
      本例中,每个小球都是可以拖拽的。enterFrame 函数负责为小球调用 springTo 函数。
请注意,这两条语句都是由两条判断语句包围起来的,目的是要确认小球目前没被拖拽:
springTo(ball0, ball1);
springTo(ball1, ball0);
      springTo 函数用于产生运动,函数中的所有语句大家应该都很熟悉。首先,求出距离
和角度,再计算目标点,然后向目标点运动。第二次调用函数时,参数相反,两个小球交换
位置,开始的小球向另一个小球运动。这也许不是效率最高的代码,但是它可以最好地表现
出运动的过程。
    我们看到,小球不会依附在任何固定点上,它们都是自由飘浮的。小球之间唯一的约束
就是彼此保持一定的距离。这种写法最好的地方是可以很容易地加入新的物体。例如,再创
建第三个小球(ball2),同时为它设置一个变量(ball2Dragging),就可以这么添加:
if(!ball0Dragging) {
    springTo(ball0, ball1);
    springTo(ball0, ball2);
}
if(!ball1Dragging) {
    springTo(ball1, ball0);
    springTo(ball1, ball2);
}
if(!ball2Dragging) {
    springTo(ball2, ball0);
    springTo(ball2, ball1);
}
    这样就建立了一个三角形结构,如图 8-7 所示。大家熟练掌握后,很快就能做出四边
形结构,直到一切复杂的弹簧结构。
本章重要公式总结
现在来回顾一下本章的重要公式
简单缓动,长形:
var dx:Number = targetX - sprite.x;
var dy:Number = targetY - sprite.y;
vx = dx * easing;
vy = dy * easing;
sprite.x += vx;
sprite.y += vy;
简单缓动,中形:
vx = (targetX - sprite.x) * easing;
vy = (targetY - sprite.y) * easing;
sprite.x += vx;
sprite.y += vy;
简单缓动,短形:
sprite.x += (targetX - sprite.x) * easing;
sprite.y += (targetY - sprite.y) * easing;
简单弹性,长形:
var ax:Number = (targetX - sprite.x) * spring;
var ay:Number = (targetY - sprite.y) * spring;
vx += ax;
vy += ay;
vx *= friction;
vy *= friction;
sprite.x += vx;
sprite.y += vy;
简单弹性,中形:
vx += (targetX - sprite.x) * spring;
vy += (targetY - sprite.y) * spring;
vx *= friction;
vy *= friction;
sprite.x += vx;
sprite.y += vy;
简单弹性,短形:
vx += (targetX - sprite.x) * spring;
vy += (targetY - sprite.y) * spring;
sprite.x += (vx *= friction);
sprite.y += (vy *= friction);
偏移弹性运动:
var dx:Number = sprite.x - fixedX;
var dy:Number = sprite.y - fixedY;
var angle:Number = Math.atan2(dy, dx);
var targetX:Number = fixedX + Math.cos(angle) * springLength;
var targetY:Number = fixedX + Math.sin(angle) * springLength;

AS3缓动类Tweenlite的使用说明 AS3缓动类Tweenlite的使用说明,帮助您更方便的使用TweenLite。 立即下载

相关推荐

小球运动 AS3.0`

test your individual AS3 skills with within the Flash environment, as well as your ability to implement the behaviour for a given design. You will be given a Flash Document (.fla) containing 3 Library Assets and example of the finished end product (.swf). Asteriod movement, and can be reseved

AS3.0写的一个滚动条【缓动效果】

package {    import flash.display.MovieClip;    import flash.events.MouseEvent;    import flash.events.Event;    import flash.geom.Rectangle;        public class myScrollBar extends MovieClip    {    ...

hereson 772

AS3.0缓动效果(可用于触摸屏)

AS3.0缓动效果,网上找到的资源~~~

as缓动类的用法

AS中可用Tween类来创建一个缓动的变换效果。 var 缓动实例名:Tween=new Tween(要实现变换的对象,"要变换的参数(x,y,scaleX,scaleY,alpha,roatation)" ,缓动类型,起始值,结束值,变换的时间,是否以秒为单位); 起始值:指变换开始时对象的参数值,缩放和透明度1表示原来,以小数来表示。 结束值:指变换后对象的参数值。 可以应用多个缓动来实现对象

xingxinmanong的博客 989

缓动 TweenMax 非常强大的as3.0缓动类

缓动 TweenMax 非常强大的as3.0缓动类,直接导入到文档类中即可使用,非常方便!

Tweener 缓动类 (AS3)

Tweener是为flash开发的补间引擎,多年来赢得了相当多用户的欢迎。 这个包的顶层目录叫做caurina。把这个文件夹放到与你其他的项目文件相同的文件夹(或者其他你的开发环境能找到的地方)。这个引擎的主类是 caurina.transitions.Tweener。 Tweener的语法很容易适应。与Adobe的Tween类不同,你不需要实例化主类Tweener。而是调用Tweener的静态方法。主要的方法是addTween。就像这样: Tweener.addTween(target, tweeningParameters);

AS3 控制按钮的缓动缩放

以下类,可以直接设置为启动类,运行看到效果: package { import flash.display.Graphics; import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent;

Jave.Lin 的学习笔记 2352

AS3 Tweener缓动类库

使用Tweener可以轻松建立各种动画,简单容易上手

转 第八章 缓动与弹性运动(1)(as3.0)

很难相信我们居然用了七章才把基础的内容介绍完,现在进入第八章,这里是高级内容 的起点。从这里开始内容也开始变得越来越有趣了,前面的章节都是些常用的概念与技术。 从今天开始,每章只着重介绍一两种特殊的运动。      本章将介绍缓动运动(成比例速度)与弹性运动(成比例加速度)

roadProgram的专栏 1999

Reeds-Shepp曲线公式推导及代码实现-第二部分(共三部分)

文章目录2. Reeds-Shepp求解2.1 L+S+L+L^+S^+L^+L+S+L+2.2 L+S+R+L^+S^+R^+L+S+R+2.3 L+R−L+L^+R^-L^+L+R−L+2.4 L+R−L−L^+R^-L^-L+R−L−2.5 L+R+L−L^+R^+L^-L+R+L−2.6 L+Rβ+Lβ−R−L^+R_{\beta}^+L_{\beta}^-R^-L+Rβ+​Lβ−​R−2.7 L+Rβ−Lβ−R+L^+R_{\beta}^-L_{\beta}^-R^+L+Rβ−​Lβ−​R+2.8

jianmo的博客 1213

三极管和MOS管工作原理详解

PN结的形成 PN结是三极管以及场效应管中最基本的组成部分,要想彻底搞明白三极管以及场效应管的工作原理,必须先搞清楚PN结形成的原理和工作特性。 本征半导体以及空穴对 本征半导体(intrinsic semiconductor))完全不含杂质且无晶格缺陷的纯净半导体称为本征半导体。主要常见代表有硅、锗这两种元素的单晶体结构。硅、锗都是4价原子,在半导体内部形成相对稳定的共价键结构,如图 1所

技术交流是便宜的的博客 10万+

【as3】ActionScript 3.0体验试教学视频教程

很不错的视频教程 原文地址: [url=http://blog.sina.com.cn/s/blog_3ecb9b1101009nx0.html]http://blog.sina.com.cn/s/blog_3ecb9b1101009nx0.html[/url]   全屏观看地址: [url=http://vhead.blog.sina.com.cn/player/outer_pla...

hgfghe7 127

高压脉冲发生器的各种电路图

高压脉冲发生器的各种电路图

qq_65102825的博客 5908
上一篇: 转 第八章 缓动与弹性运动(1)(as3.0)
下一篇: 转 第九章 碰撞检测(as3.0)
coding_most
博客等级 码龄15年 13粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值