zoukankan      html  css  js  c++  java
  • Flash/Flex学习笔记(39):弹性运动

    动画中的弹性运动 从视觉效果上接近 物理经典力学中的单摆运动或弹簧(胡克定律F=Kx)振动

    先看下面的模拟演示:

    规律:
    小球先从出发点(初始为最左侧)向目标点(中心点)加速狂奔,奔的过程中速度越来越大,但加速度越来越小,等经过目标点时,发现速度太大刹不住车(此时速度达到最大值,但加速度减为0),奔过头了!于是加速度发生逆转,从0开始变为负值,从而导致速度越来越小,等速度减到0时,也奔到了最右侧(此时负加速度也达到最大值),然后在负加速度的影响下,开始掉头又狂奔....这样不断下去,直接摩擦力让它筋疲力尽,最终瘫倒在目标点 :)

    公式:胡克定律F=Kx,而合外力F根据牛二定律 F=ma,这二者结合起来换算一下,也就是 ma = kx,即a = (k/m)x .用代码体现出来,即加速度与位移成(正比)线性关系。

    show sourceview source

    print?

    01
    package {

    02
    import flash.display.Sprite;

    03
    import flash.events.Event;

    04
    import flash.events.MouseEvent;

    05
    import flash.geom.Rectangle;

    06
    import flash.ui.Mouse;

    07
    import flash.ui.MouseCursor;

    08

    09
    public class Spring1 extends Sprite {

    10
    private var ball:Ball;

    11
    private var spring:Number=0.02;

    12
    private var targetX:Number=stage.stageWidth/2;

    13
    private var rect:Rectangle;

    14
    private var vx:Number=0;

    15
    private var isDragging=false;

    16

    17
    public function Spring1() {

    18
    init();

    19
    }

    20

    21
    private function init():void {

    22
    ball=new Ball(10);

    23
    addChild(ball);

    24
    ball.x=20;

    25
    ball.y=stage.stageHeight/2;

    26
    addEventListener(Event.ENTER_FRAME, onEnterFrame);

    27

    28
    ball.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

    29
    ball.addEventListener(MouseEvent.MOUSE_OVER,function(){Mouse.cursor = MouseCursor.HAND});

    30
    ball.addEventListener(MouseEvent.MOUSE_OUT,MouseOutHandler);

    31
    stage.addEventListener(MouseEvent.MOUSE_UP,MouseUpHandler);

    32

    33
    //画辅助线

    34
    graphics.lineStyle(1);

    35
    graphics.moveTo(ball.x,ball.y);

    36
    graphics.lineTo(stage.stageWidth-ball.x,ball.y);

    37
    graphics.moveTo(stage.stageWidth/2,ball.y-10);

    38
    graphics.lineTo(stage.stageWidth/2,ball.y+10);

    39

    40
    rect=new Rectangle(ball.x,ball.y,stage.stageWidth-2*ball.x,0);

    41
    }

    42

    43
    private function MouseOutHandler() {

    44
    if (! isDragging) {

    45
    Mouse.cursor=MouseCursor.AUTO;

    46
    }

    47
    }

    48

    49

    50
    //开始拖动

    51
    private function MouseDownHandler(e:MouseEvent):void {

    52
    ball.startDrag(true,rect);

    53
    Mouse.cursor=MouseCursor.HAND;

    54
    removeEventListener(Event.ENTER_FRAME, onEnterFrame);

    55
    isDragging=true;

    56

    57
    }

    58

    59
    //结束拖动

    60
    private function MouseUpHandler(e:MouseEvent):void {

    61
    ball.stopDrag();

    62
    addEventListener(Event.ENTER_FRAME, onEnterFrame);

    63
    Mouse.cursor=MouseCursor.AUTO;

    64
    isDragging=false;

    65
    }

    66

    67
    private function onEnterFrame(event:Event):void {

    68
    var dx:Number = targetX-ball.x;

    69
    var ax:Number = dx*spring;//加速度与位移成正(反)比关系

    70
    vx += ax;

    71
    vx *= 0.97;//摩擦系数

    72
    trace(ax,vx);

    73
    ball.x+=vx;

    74

    75
    }

    76
    }

    77
    }

    上面演示是一维的弹性运动,当然也可以同时在x轴和y轴上进行

    代码:

    show sourceview source

    print?

    01
    package {

    02
    import flash.display.Sprite;

    03
    import flash.events.Event;

    04
    import flash.events.MouseEvent;

    05
    import flash.ui.Mouse;

    06
    import flash.ui.MouseCursor;

    07

    08
    public class Spring2 extends Sprite {

    09
    private var ball:Ball;

    10
    private var spring:Number=0.1;

    11
    private var targetX:Number=stage.stageWidth/2;

    12

    13
    private var targetY:Number=stage.stageHeight/2;

    14
    private var vx:Number=0;

    15
    private var vy:Number=0;

    16
    private var friction:Number=0.95;

    17

    18
    public function Spring2() {

    19
    init();

    20
    }

    21
    private function init():void {

    22
    ball = new Ball(5);

    23
    ball.x = Math.random() * stage.stageWidth;

    24
    ball.y = Math.random() * stage.stageHeight;         

    25
    addChild(ball);

    26
    addEventListener(Event.ENTER_FRAME, EnterFrameHandler);

    27
    stage.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler); 

    28
    MouseDownHandler(null);

    29
    Mouse.cursor = MouseCursor.BUTTON;

    30
    }

    31

    32
    function MouseDownHandler(e:MouseEvent):void{

    33
    graphics.clear();

    34
    ball.x = Math.random() * stage.stageWidth;

    35
    ball.y = Math.random() * stage.stageHeight;

    36
    ball.vx = (Math.random()*2-1) * 50;

    37
    ball.vy = (Math.random()*2-1) * 50;

    38
    graphics.moveTo(ball.x,ball.y);         

    39
    }

    40

    41
    private function EnterFrameHandler(event:Event):void {

    42
    //去掉下面的注释,就变成鼠标跟随的弹性运动

    43
    //targetX = mouseX;

    44
    //targetY = mouseY;

    45
    var dx:Number=targetX-ball.x;

    46
    var dy:Number=targetY-ball.y;

    47
    var ax:Number=dx*spring;

    48
    var ay:Number=dy*spring;

    49
    vx+=ax;

    50
    vy+=ay;

    51
    vx*=friction;

    52
    vy*=friction;

    53
    ball.x+=vx;

    54
    ball.y+=vy;

    55
    graphics.lineStyle(0.3,0xbbbbbb,1);

    56
    graphics.lineTo(ball.x,ball.y);

    57
    }

    58
    }

    59
    }

    接下来:用代码模仿一根猴皮筋儿

    show sourceview source

    print?

    01
    package {

    02
    import flash.display.Sprite;

    03
    import flash.events.Event;

    04
    import flash.ui.Mouse;

    05
    import flash.ui.MouseCursor;

    06

    07
    public class Spring3 extends Sprite {

    08
    private var ball:Ball;

    09
    private var spring:Number=0.1;

    10
    private var vx:Number=0;

    11
    private var vy:Number=0;

    12
    private var friction:Number=0.95;

    13

    14

    15
    public function Spring3() {

    16
    init();

    17
    }

    18
    private function init():void {

    19
    ball = new Ball(10);

    20
    addChild(ball);

    21
    addEventListener(Event.ENTER_FRAME, onEnterFrame);

    22
    Mouse.cursor = MouseCursor.HAND;

    23
    }

    24
    private function onEnterFrame(event:Event):void {

    25
    var dx:Number = mouseX-ball.x;

    26
    var dy:Number = mouseY-ball.y;

    27
    var ax:Number = dx*spring;

    28
    var ay:Number = dy*spring;

    29
    vx+=ax;

    30
    vy+=ay;

    31

    32
    vx*=friction;

    33
    vy*=friction;

    34
    ball.x+=vx;

    35
    ball.y+=vy;

    36
    graphics.clear();

    37
    graphics.lineStyle(1);          

    38
    graphics.moveTo(mouseX, mouseY);

    39
    graphics.lineTo(ball.x, ball.y);

    40
    }

    41
    }

    42
    }

    上面的例子只有一个球,如果考虑更多的小球,第一球以鼠标所在位置为目标做弹性运动,而第二个以第一个球为目标做弹性运动,第三球又跟着第二个... 这会是什么效果呢?

    show sourceview source

    print?

    01
    package {

    02

    03
    import flash.display.Sprite;

    04
    import flash.events.MouseEvent;

    05
    import flash.events.Event;

    06

    07
    public class ArrayChain extends Sprite {

    08

    09
    var arrBall:Array;      

    10
    var spring:Number=0.12;

    11
    var firstBall:Ball;

    12
    var gravity:Number=6;

    13
    var friction:Number=0.8;

    14

    15
    public function ArrayChain() {          

    16
    init();

    17
    }

    18

    19
    private function init():void {

    20
    arrBall=new Array(5);

    21
    for (var i:uint=0,j:uint=arrBall.length; i<j; i++) {

    22
    arrBall[i]=new Ball(10,Math.random()*0xffffff);

    23
    addChild(arrBall[i]);

    24
    }

    25
    firstBall=arrBall[0];

    26
    firstBall.x=Math.random()*stage.stageWidth;

    27
    firstBall.y=Math.random()*stage.stageHeight;    

    28
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    29
    }

    30

    31
    private function EnterFrameHandler(e:Event):void {

    32
    //第一个球以鼠标所在位置为目标做弹性运动

    33
    firstBall.vx += (mouseX - firstBall.x) * spring;

    34
    firstBall.vy += (mouseY - firstBall.y) * spring;

    35
    firstBall.vy+=gravity;

    36
    firstBall.vx*=friction;

    37
    firstBall.vy*=friction;

    38
    firstBall.x+=firstBall.vx;

    39
    firstBall.y+=firstBall.vy;

    40

    41
    //准备画连线

    42
    graphics.clear();

    43
    graphics.lineStyle(0.2,0x666666);

    44
    graphics.moveTo(mouseX,mouseY);

    45
    graphics.lineTo(firstBall.x,firstBall.y);

    46

    47
    //后面的小球依次以前一个的位置为目标做弹性运动

    48
    for (var i=1,j=arrBall.length; i<j; i++) {

    49
    var ball:Ball=arrBall[i];

    50
    ball.vx += (arrBall[i-1].x-ball.x)*spring;

    51
    ball.vy += (arrBall[i-1].y-ball.y)*spring;

    52
    ball.vy+=gravity;

    53
    ball.vx*=friction;

    54
    ball.vy*=friction;

    55
    ball.x+=ball.vx;

    56
    ball.y+=ball.vy;

    57
    graphics.lineTo(ball.x,ball.y);//画出连线将各球连在一起

    58
    }

    59
    }

    60
    }

    61

    62
    }

    ok,我们得到了一个"弹簧链",当然这里面还考虑了重力的因素,通过上面的几个例子可以总结一下:第一个示例中一维弹性运动可以看作为x方向的加速度随位移的影响,而第二个示例可以看作是x,y二个方向加速度随位移影响的叠加,而第三个示例,则可以看作是任何方向这种影响再叠加重力的综合效果。总之:任何方向的弹性运动,都可以认为是该方向的加速度(或力)随位移的影响,而且这种影响可以在多个方向上叠加。下面这个是多点控制弹性运动的示例:

  • 相关阅读:
    Linux下使用Nexus搭建Maven私服
    使用Nexus搭建Maven内部服务器
    windows Maven3.0 服务器配置搭建
    Linux中more和less命令用法
    Jmeter使用入门
    【转载】 DeepMind发表Nature子刊新论文:连接多巴胺与元强化学习的新方法
    【转载】 十图详解tensorflow数据读取机制(附代码)
    【转载】 tensorflow中 tf.train.slice_input_producer 和 tf.train.batch 函数
    (待续) https://zhuanlan.zhihu.com/p/27629294
    ( 待续 ) https://zhuanlan.zhihu.com/p/57864886
  • 原文地址:https://www.cnblogs.com/happysky97/p/1884574.html
Copyright © 2011-2022 走看看