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

    上一篇里演示的弹性运动加上摩擦力因素后,物体最终基本上都会比较准确的停在目标位置。但是我们回想一下现实世界中的弹簧,如果把弹簧的一头固定起来(即相当于目标点),而另一端栓一个球,把球拉开或压缩一定距离然后松手,事实上小球永远也不可能到达弹簧固定的那一端(因为弹簧即使压缩到最紧,也总有一定的长度)

    所以如果要在Flash里模拟现实中的弹簧,真正的目标点绝不是弹簧的端点,而是目标点再偏移一段距离(即弹簧自然伸展时的长度)

    show sourceview source

    print?

    01
    var ball:Ball = new Ball(6);

    02
    addChild(ball);

    03
    ball.y = 20;

    04
    ball.x = 20;

    05

    06
    var targetX:Number=stage.stageWidth/2;

    07
    var targetY:Number=ball.y;

    08

    09
    var springLength = 100;//弹簧长度

    10
    var spring = 0.2;//弹性系数

    11
    var friction = 0.92;//摩擦系数

    12

    13
    //画辅助线,以便看得更清楚

    14
    graphics.lineStyle(0.5,0xaaaaaa);

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

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

    17
    graphics.moveTo(targetX,targetY-10);

    18
    graphics.lineTo(targetX,targetY+10);

    19
    graphics.moveTo(targetX-springLength,targetY-8);

    20
    graphics.lineTo(targetX-springLength,targetY+8);

    21

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

    23

    24
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

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

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

    27

    28
    function EnterFrameHandler(e:Event):void{

    29
    ball.vx += (targetX - springLength - ball.x)*spring;

    30
    ball.vx *= friction;

    31
    ball.x += ball.vx;

    32
    }

    33

    34
    function MouseDownHandler(e:MouseEvent):void{

    35
    (e.target as Sprite).startDrag(true,rect);

    36
    removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    37
    }

    38

    39
    function MouseUpHandler(e:MouseEvent):void{

    40
    ball.stopDrag();

    41
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    42
    }

    43

    44
    ball.addEventListener(MouseEvent.MOUSE_OUT,function(){Mouse.cursor = MouseCursor.AUTO});

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

    如果考虑到二维坐标的弹簧运动,要稍微复杂一点:

    show sourceview source

    print?

    01
    var ball:Ball = new Ball(10);

    02
    addChild(ball);

    03
    ball.y = 20;

    04
    ball.x = 20;

    05

    06
    var targetX:Number=stage.stageWidth/2;

    07
    var targetY:Number=stage.stageHeight/2;

    08

    09
    var springLength:uint = 100;//弹簧长度

    10
    var spring:Number = 0.2;//弹性系数

    11
    var friction:Number = 0.92;//摩擦系数

    12
    var angle:Number = 0;

    13

    14
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

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

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

    17
    stage.addEventListener(MouseEvent.MOUSE_MOVE,function(){DrawLine()});

    18

    19
    angle = Math.atan2(targetY - ball.y,targetX -ball.x);//确定夹角

    20
    trace(angle*180/Math.PI);

    21

    22
    function EnterFrameHandler(e:Event):void{

    23
    ball.vx += (targetX - springLength*Math.cos(angle) - ball.x)*spring;//调整目标点

    24
    ball.vy += (targetY - springLength*Math.sin(angle) - ball.y)*spring;

    25
    ball.vx *= friction;

    26
    ball.vy *= friction;

    27
    ball.x += ball.vx;

    28
    ball.y += ball.vy;

    29
    DrawLine();

    30
    }

    31

    32
    function DrawLine():void{

    33
    graphics.clear();

    34
    graphics.lineStyle(1);

    35
    graphics.moveTo(targetX,targetY-10);

    36
    graphics.lineTo(targetX,targetY+10);

    37
    graphics.moveTo(targetX-10,targetY);

    38
    graphics.lineTo(targetX+10,targetY);

    39
    graphics.moveTo(targetX,targetY);

    40
    graphics.lineStyle(0.5,0xaaaaaa);

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

    42
    }

    43

    44
    function MouseDownHandler(e:MouseEvent):void{

    45
    (e.target as Sprite).startDrag(true);

    46
    removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    47
    }

    48

    49
    function MouseUpHandler(e:MouseEvent):void{

    50
    ball.stopDrag();

    51
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    52
    }

    53

    54
    ball.addEventListener(MouseEvent.MOUSE_OUT,function(){Mouse.cursor = MouseCursor.AUTO});

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

    上面的例子中,移动的方向(即夹角)与目标点都是固定的,如果改成动态的(比如鼠标当前所在位置),效果可能更逼真

    view source

    print?

    01
    function EnterFrameHandler(e:Event):void{

    02
    targetX = mouseX;//改成动态目标

    03
    targetY = mouseY;

    04
    angle = Math.atan2(targetY - ball.y,targetX -ball.x);//动态夹角

    05
    ball.vx += (targetX - springLength*Math.cos(angle) - ball.x)*spring;

    06
    ball.vy += (targetY - springLength*Math.sin(angle) - ball.y)*spring;

    07
    ball.vx *= friction;

    08
    ball.vy *= friction;

    09
    ball.x += ball.vx;

    10
    ball.y += ball.vy;

    11
    DrawLine();

    12
    }

    如果二个物体相互以对方所在位置为目标做弹性运动,同时再考虑弹簧长度,边界检测等因素,可以用AS3模拟出一个极逼真的弹簧模型:

    show sourceview source

    print?

    01
    var ball_1:Ball = new Ball(10,0xff0000);

    02
    var ball_2:Ball = new Ball(10,0x0000ff);

    03
    ball_1.x = stage.stageWidth * Math.random();

    04
    ball_1.y = stage.stageHeight * Math.random();

    05
    ball_2.x = stage.stageWidth/2;

    06
    ball_2.y = stage.stageHeight/2;

    07

    08
    addChild(ball_1);

    09
    addChild(ball_2);

    10

    11
    var spring:Number = 0.1;

    12
    var springLength:uint = 100;

    13
    var friction:Number = 0.9;

    14
    var darggingBall:Ball;

    15

    16
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    17
    ball_1.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

    18
    ball_2.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

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

    20
    stage.addEventListener(MouseEvent.MOUSE_MOVE,function(){DrawLine();});

    21
    ball_1.addEventListener(MouseEvent.MOUSE_OVER,MouseOverHandler);

    22
    ball_1.addEventListener(MouseEvent.MOUSE_OUT,MouseOutHandler);

    23
    ball_2.addEventListener(MouseEvent.MOUSE_OVER,MouseOverHandler);

    24
    ball_2.addEventListener(MouseEvent.MOUSE_OUT,MouseOutHandler);

    25

    26
    function MouseOutHandler(e:MouseEvent){

    27
    Mouse.cursor = MouseCursor.AUTO;

    28
    }

    29

    30
    function MouseOverHandler(e:MouseEvent){

    31
    Mouse.cursor = MouseCursor.HAND;

    32
    }

    33

    34
    function MouseDownHandler(e:MouseEvent):void{

    35
    (e.target as Sprite).startDrag(true,new Rectangle(20,20,stage.stageWidth-40,stage.stageHeight-40));

    36
    darggingBall = e.target as Ball;

    37
    removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    38
    }

    39

    40
    function MouseUpHandler(e:MouseEvent):void{

    41
    if (darggingBall!=null){

    42
    darggingBall.stopDrag();

    43
    darggingBall = null;

    44
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    45
    }   

    46
    }

    47

    48
    function EnterFrameHandler(e:Event):void{

    49
    var dx1 = ball_2.x -ball_1.x;

    50
    var dy1 = ball_2.y -ball_1.y;   

    51
    var angle1:Number = Math.atan2(dy1,dx1);    

    52
    ball_1.vx += (ball_2.x - springLength * Math.cos(angle1) - ball_1.x) * spring;

    53
    ball_1.vy += (ball_2.y - springLength * Math.sin(angle1) - ball_1.y) * spring;  

    54
    ball_1.vx *= friction;

    55
    ball_1.vy *= friction;  

    56
    ball_1.x += ball_1.vx;

    57
    ball_1.y += ball_1.vy;

    58

    59

    60
    var dx2 = ball_1.x -ball_2.x;

    61
    var dy2 = ball_1.y -ball_2.y;   

    62
    var angle2:Number = Math.atan2(dy2,dx2);    

    63
    ball_2.vx += (ball_1.x - springLength * Math.cos(angle2) - ball_2.x) * spring;

    64
    ball_2.vy += (ball_1.y - springLength * Math.sin(angle2) - ball_2.y) * spring;  

    65
    ball_2.vx *= friction;

    66
    ball_2.vy *= friction;  

    67
    ball_2.x += ball_2.vx;

    68
    ball_2.y += ball_2.vy;

    69

    70
    DrawLine();

    71

    72
    CheckBoundary(ball_1);

    73
    CheckBoundary(ball_2);

    74

    75

    76
    }

    77

    78
    function DrawLine():void{

    79
    graphics.clear();

    80
    graphics.lineStyle(0.5,0x666666);

    81
    graphics.moveTo(ball_1.x,ball_1.y);

    82
    graphics.lineTo(ball_2.x,ball_2.y);

    83
    }

    84

    85
    function CheckBoundary(b:Ball){

    86
    if (b.x>stage.stageWidth-b.width/2 || b.x<=b.width/2){

    87
    b.x -= b.vx;        

    88
    b.vx *= -1;

    89
    }

    90

    91
    if (b.y>stage.stageHeight-b.height/2 || b.y<=b.height/2){

    92
    b.y -= b.vy;

    93
    b.vy *= -1;

    94
    }

    95
    }

    如果玩得再疯狂一点,多放一些小球,让第二个以第一个为目标,第三个以第二个为目标...最后一个再以第一个为目标,这样构成一个环,大概就是下面这个样子:

    show sourceview source

    print?

    001
    var spring:Number=0.1;

    002
    var springLength:uint=150;

    003
    var friction:Number=0.8;//摩擦力

    004
    var darggingBall:Ball;

    005
    var ballNumber:uint = 3;//小球个数

    006

    007
    var arrBalls:Array = new Array(ballNumber);

    008

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

    010
    arrBalls[i] = new Ball(20,Math.random() * 0xffffff);

    011
    var _ball:Ball = arrBalls[i];

    012
    _ball.x=stage.stageWidth*Math.random();

    013
    _ball.y=stage.stageHeight*Math.random();

    014
    addChild(_ball);

    015
    _ball.addEventListener(MouseEvent.MOUSE_OVER,MouseOverHandler);

    016
    _ball.addEventListener(MouseEvent.MOUSE_OUT,MouseOutHandler);

    017
    _ball.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

    018
    }

    019

    020
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    021

    022

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

    024
    stage.addEventListener(MouseEvent.MOUSE_MOVE,function(){DrawLine();});

    025

    026

    027
    //切换光标

    028
    function MouseOutHandler(e:MouseEvent) {

    029
    Mouse.cursor=MouseCursor.AUTO;

    030
    }

    031

    032
    //切换光标

    033
    function MouseOverHandler(e:MouseEvent) {

    034
    Mouse.cursor=MouseCursor.HAND;

    035
    }

    036

    037
    //开始拖动

    038
    function MouseDownHandler(e:MouseEvent):void {

    039
    (e.target as Sprite).startDrag(true,new Rectangle(20,20,stage.stageWidth-40,stage.stageHeight-40));

    040
    darggingBall=e.target as Ball;

    041
    removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    042
    }

    043

    044
    //结束拖动

    045
    function MouseUpHandler(e:MouseEvent):void {

    046
    if (darggingBall!=null) {

    047
    darggingBall.stopDrag();

    048
    darggingBall=null;

    049
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    050
    }

    051
    }

    052

    053
    function EnterFrameHandler(e:Event):void {

    054

    055
    for(var i:uint=0,j=arrBalls.length-1;i<j;i++){

    056
    SpringTo(arrBalls[i],arrBalls[i+1]);        

    057
    }

    058
    SpringTo(arrBalls[arrBalls.length-1],arrBalls[0]);

    059

    060
    DrawLine(); 

    061

    062
    for(i=0,j=arrBalls.length;i<j;i++){

    063
    CheckBoundary(arrBalls[i]);

    064
    }

    065

    066

    067
    }

    068

    069

    070
    //画连接线

    071
    function DrawLine():void {

    072
    graphics.clear();

    073
    graphics.lineStyle(0.5,0x666666);

    074
    //graphics.moveTo(ball_1.x,ball_1.y);

    075
    //graphics.lineTo(ball_2.x,ball_2.y);

    076

    077
    for(var i:uint=0,j=arrBalls.length-1;i<j;i++){

    078
    graphics.moveTo(arrBalls[i].x,arrBalls[i].y);

    079
    graphics.lineTo(arrBalls[i+1].x,arrBalls[i+1].y);

    080
    }

    081
    graphics.lineTo(arrBalls[0].x,arrBalls[0].y);

    082
    }

    083

    084
    //弹性运动处理

    085
    function SpringTo(targetBall:Ball,moveBall:Ball):void{

    086
    var dy=targetBall.y-moveBall.y;

    087
    var dx=targetBall.x-moveBall.x; 

    088
    var angle1:Number=Math.atan2(dy,dx);

    089
    moveBall.vx += (targetBall.x - springLength * Math.cos(angle1) - moveBall.x) * spring;

    090
    moveBall.vy += (targetBall.y - springLength * Math.sin(angle1) - moveBall.y) * spring;

    091
    moveBall.vx *= friction;

    092
    moveBall.vy *= friction;

    093
    moveBall.x += moveBall.vx;

    094
    moveBall.y += moveBall.vy;

    095
    }

    096

    097
    //检测边界

    098
    function CheckBoundary(b:Ball) {

    099
    if (b.x>stage.stageWidth-b.width/2||b.x<=b.width/2) {

    100
    b.x-=b.vx;

    101
    b.vx*=-1;

    102
    }

    103

    104
    if (b.y>stage.stageHeight-b.height/2||b.y<=b.height/2) {

    105
    b.y-=b.vy;

    106
    b.vy*=-1;

    107
    }

    108
    }

    思考一下:这样为啥不会造成死循环?

  • 相关阅读:
    【sqli-labs】 less61 GET -Challenge -Double Query -5 queries allowed -Variation4 (GET型 挑战 双查询 只允许5次查询 变化4)
    Spring overview
    Code First use dotConnect for MySQL
    讓 MySQL 能夠用 EF6
    Sublime Text 3 常用插件以及安装方法(转)
    EntityFramework 6.0< Code First > 连接 Mysql数据库(转)
    bootstrap 2.3版与3.0版的使用区别
    用google-code-prettify高亮代码
    MVC中的@Html.DisplayFor等方法如何控制日期的显示格式(转)
    给Jquery easyui 的datagrid 每行增加操作链接(转)
  • 原文地址:https://www.cnblogs.com/happysky97/p/1884575.html
Copyright © 2011-2022 走看看