`
madfroghe
  • 浏览: 121370 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Flash/Flex学习笔记(35):弹性运动续--弹簧

阅读更多

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

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

var ball:Ball = new Ball(6);


addChild(ball);


ball.y = 20;

 
ball.x = 20;

var targetX:Number=stage.stageWidth/2;


var targetY:Number=ball.y;

 
var springLength = 100;//弹簧长度

 
var spring = 0.2;//弹性系数

 
var friction = 0.92;//摩擦系数

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

 
graphics.lineStyle(0.5,0xaaaaaa);

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

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

 
graphics.moveTo(targetX,targetY-10);

 
graphics.lineTo(targetX,targetY+10);

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

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

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

 
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);


ball.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

 
stage.addEventListener(MouseEvent.MOUSE_UP,MouseUpHandler);

function EnterFrameHandler(e:Event):void{

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


ball.vx *= friction;

 
ball.x += ball.vx;


}

 
function MouseDownHandler(e:MouseEvent):void{

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

 
removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
}

 


function MouseUpHandler(e:MouseEvent):void{

 
ball.stopDrag();

 
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);


}


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


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

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

 

var ball:Ball = new Ball(10);

 
addChild(ball);

 
ball.y = 20;


ball.x = 20;


var targetX:Number=stage.stageWidth/2;

 
var targetY:Number=stage.stageHeight/2;

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

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

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

 
var angle:Number = 0;


addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
ball.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

 
stage.addEventListener(MouseEvent.MOUSE_UP,MouseUpHandler);

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

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

 
trace(angle*180/Math.PI);

 
function EnterFrameHandler(e:Event):void{

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

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

 
ball.vx *= friction;

 
ball.vy *= friction;

 
ball.x += ball.vx;

 
ball.y += ball.vy;

 
DrawLine();

 
}


function DrawLine():void{

 
graphics.clear();


graphics.lineStyle(1);


graphics.moveTo(targetX,targetY-10);

 
graphics.lineTo(targetX,targetY+10);

 
graphics.moveTo(targetX-10,targetY);

 
graphics.lineTo(targetX+10,targetY);

 
graphics.moveTo(targetX,targetY);

 
graphics.lineStyle(0.5,0xaaaaaa);

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

 
}

 
function MouseDownHandler(e:MouseEvent):void{

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


removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
}

 
function MouseUpHandler(e:MouseEvent):void{


ball.stopDrag();

 
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
}

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

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

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

 
function EnterFrameHandler(e:Event):void{

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

 
targetY = mouseY;


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

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

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

 
ball.vx *= friction;

 
ball.vy *= friction;


ball.x += ball.vx;

 
ball.y += ball.vy;

 
DrawLine();

}

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

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


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

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

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

 
ball_2.x = stage.stageWidth/2;

 
ball_2.y = stage.stageHeight/2;

 
addChild(ball_1);

 
addChild(ball_2);

 
var spring:Number = 0.1;

 
var springLength:uint = 100;

 
var friction:Number = 0.9;

 
var darggingBall:Ball;

 
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
ball_1.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

 
ball_2.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

 
stage.addEventListener(MouseEvent.MOUSE_UP,MouseUpHandler);

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

 
ball_1.addEventListener(MouseEvent.MOUSE_OVER,MouseOverHandler);

 
ball_1.addEventListener(MouseEvent.MOUSE_OUT,MouseOutHandler);

 
ball_2.addEventListener(MouseEvent.MOUSE_OVER,MouseOverHandler);

 
ball_2.addEventListener(MouseEvent.MOUSE_OUT,MouseOutHandler);

 
function MouseOutHandler(e:MouseEvent){

 
Mouse.cursor = MouseCursor.AUTO;

 
}

 
function MouseOverHandler(e:MouseEvent){

 
Mouse.cursor = MouseCursor.HAND;

 
}

function MouseDownHandler(e:MouseEvent):void{

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

 
darggingBall = e.target as Ball;

 
removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
}

 
function MouseUpHandler(e:MouseEvent):void{

 
if (darggingBall!=null){

 
darggingBall.stopDrag();

 
darggingBall = null;

 
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
}   

 
}

 
function EnterFrameHandler(e:Event):void{

 
var dx1 = ball_2.x -ball_1.x;


var dy1 = ball_2.y -ball_1.y;   

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


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

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

 
ball_1.vx *= friction;

 
ball_1.vy *= friction;  

 
ball_1.x += ball_1.vx;

 
ball_1.y += ball_1.vy;

 
var dx2 = ball_1.x -ball_2.x;

 
var dy2 = ball_1.y -ball_2.y;   


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

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

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

 
ball_2.vx *= friction;

 
ball_2.vy *= friction;  

 
ball_2.x += ball_2.vx;

 
ball_2.y += ball_2.vy;

 
DrawLine();

 
CheckBoundary(ball_1);


CheckBoundary(ball_2);

 
}

 
function DrawLine():void{

 
graphics.clear();

 
graphics.lineStyle(0.5,0x666666);

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

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


}

 
function CheckBoundary(b:Ball){

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

 
b.x -= b.vx;        


b.vx *= -1;

 
}

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

 
b.y -= b.vy;

 
b.vy *= -1;

 
}

 
}

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


var spring:Number=0.1;

 
var springLength:uint=150;

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

 
var darggingBall:Ball;


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


var arrBalls:Array = new Array(ballNumber);

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

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

 
var _ball:Ball = arrBalls[i];

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

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

 
addChild(_ball);

 
_ball.addEventListener(MouseEvent.MOUSE_OVER,MouseOverHandler);


_ball.addEventListener(MouseEvent.MOUSE_OUT,MouseOutHandler);

 
_ball.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

 
}


addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 

 

stage.addEventListener(MouseEvent.MOUSE_UP,MouseUpHandler);

 

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

 
//切换光标

 
function MouseOutHandler(e:MouseEvent) {

 
Mouse.cursor=MouseCursor.AUTO;

 
}


//切换光标

 
function MouseOverHandler(e:MouseEvent) {

 
Mouse.cursor=MouseCursor.HAND;

 
}

 
//开始拖动

 
function MouseDownHandler(e:MouseEvent):void {

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

 
darggingBall=e.target as Ball;

 
removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
}

 
//结束拖动

 
function MouseUpHandler(e:MouseEvent):void {


if (darggingBall!=null) {

 
darggingBall.stopDrag();

 
darggingBall=null;

 
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);


}

 
}


function EnterFrameHandler(e:Event):void {

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

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

 
}

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

 
DrawLine(); 

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


CheckBoundary(arrBalls[i]);

 
}

 
}


//画连接线

 
function DrawLine():void {

 
graphics.clear();

 
graphics.lineStyle(0.5,0x666666);

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

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

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

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

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

 
}

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

 
}

 
//弹性运动处理  
function SpringTo(targetBall:Ball,moveBall:Ball):void{

 
var dy=targetBall.y-moveBall.y;

 
var dx=targetBall.x-moveBall.x; 

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

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


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

 
moveBall.vx *= friction;

 
moveBall.vy *= friction;

 
moveBall.x += moveBall.vx;

 
moveBall.y += moveBall.vy;

 
}

 
//检测边界

 
function CheckBoundary(b:Ball) {

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

 
b.x-=b.vx;

 
b.vx*=-1;

 
}

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


b.y-=b.vy;


b.vy*=-1;

 
}

}

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

分享到:
评论

相关推荐

    Flash/Flex 框架应用 Cairngorm、Mate、PureMVC以及Swiz 的典型例子

    附件是关于 Flash/Flex 几个重要框架 Cairngorm、Mate、PureMVC以及Swiz 的典型例子,由 Tony Hillerson 提供 Homepage: http://insideria.com

    flex/Flash开发系列书籍:WEB3D应用研究

    flex/Flash开发系列书籍:基于FLASH的WEB3D应用研究

    RE/flex lexical analyzer generator:以正则表达式为中心的快速词法分析器生成器,用于C ++-开源

    RE / flex是快速的词法分析器生成器(比Flex快),具有完整的Unicode支持,缩进/缩进/缩进锚,惰性量词和许多其他现代功能。 接受Flex lexer规范语法,并与Bison / Yacc解析器兼容。 生成易于理解的可重用源代码。 ...

    [Flash/Flex] 使用css定义文本样式

    在IT行业中,Flash和Flex是曾经非常流行的富互联网应用程序(RIA)开发框架,它们主要用于创建交互式的网页内容和应用程序。本文将重点讲解如何在Flash或Flex项目中利用CSS(层叠样式表)来定义文本样式,提升用户...

    flash/flex画曲线,绘图板

    在IT行业中,Flash/Flex是一种基于ActionScript编程语言和Adobe Flex框架的开发工具,用于创建交互式的、富媒体的Web应用程序。"Flash/Flex画曲线,绘图板"这个主题涉及的是如何使用这些技术来创建一个允许用户自由...

    gcc-linaro-arm-linux-gnueabihf 4.9

    apt-get install git gnupg flex bison gperf build-essential zip curl libc6-dev libncurses5-dev:i386 x11proto-core-dev libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx-lts-trusty:i386 libgl1-mesa-...

    FDT-flash/flex devtoolkit for eclipse.

    **FDT - 一款强大的Flash/Flex开发工具集** FDT(Flash Development Tool)是一款专为Adobe Flash和Flex开发者设计的集成开发环境(IDE),它基于Eclipse平台,提供了高效、专业的开发工具和服务。FDT的出现极大地...

    Flex布局笔记.docx

    - `flex`:属性简写,一次设置`flex-grow`, `flex-shrink`和`flex-basis`,如`flex: 1 0 auto`表示增长比例为1,不收缩,基础大小为自动。 通过这些属性的组合使用,开发者可以创建出各种复杂的动态布局,适应不同...

    (微信小程序毕业设计)电器租赁小程序

    flex-direction: row; } .nav { flex-wrap: wrap; justify-content: center; padding-top: 20rpx; background: #fff; } .nav-item { margin: 30rpx 50rpx 10rpx; width: 80rpx; } .nav-item image { ...

    FLEX安装方法 集成到eclipse中

    FLEX 是一种基于 Adobe Flash 平台的 Rich Internet Application(RIA)开发框架。它提供了一个强大且灵活的开发环境,允许开发者快速构建跨平台、跨浏览器的 Rich Internet 应用程序。在本节中,我们将介绍如何安装...

    RTMP直播例子--基于FLASH/FLEX(含源代码) 下载

    在这个“RTMP直播例子--基于FLASH/FLEX(含源代码) 下载”中,我们可以深入探讨RTMP直播的基本原理、FLEX编程以及如何在实际项目中应用这些技术。 首先,RTMP协议的工作原理是通过建立一个持久性的TCP连接,允许...

    flex滚动条三种实现方式

    在前端开发中,Flex布局(Flexible Box)是一种用于创建弹性盒模型的CSS3模块,它极大地增强了网页布局的灵活性。而当内容超出容器时,滚动条的出现是必不可少的。在Flex布局中,我们可以有几种不同的方法来实现滚动...

    4个简单的Flex例子(包含custom-class-mapping)共享

    总共有4个例子: 1.http://127.0.0.1:8080/flexDemo/HelloWorld/HelloWorld.html ...如果你的数据库配置和我的不一样,请修改flexDemo\WEB-INF\classes\下的DBSetting.properties文件,数据库建表的sql语句是user.sql

    plugin-flex:Twilio CLI插件可与Flex插件构建器进行交互

    @ twilio-labs / plugin-flex Twilio CLI插件可与进行交互该插件为添加了功能,以便在本地开发,构建和部署; 它使用 。要求安装Twilio CLI 通过npm或yarn : $ npm install -g twilio-cli$ yarn global add twilio-...

    flex开源项目介绍.doc

    9. Flex-object-handles(http://code.google.com/p/flex-object-handles/):对象处理组件,功能强大,但可能需要根据具体需求进行调整。 10. CheckboxTree 和 Carousel组件...

    flex学习笔记 flex学习总结 flex学习教程

    本教程是作者精心编写的Flex学习资料,适合初学者入门,通过图文并茂的方式,帮助读者快速掌握Flex的基本概念和核心技能。 1. **Flex基础**:Flex提供了MXML和ActionScript两种编程方式。MXML是一种声明式语言,...

    前端移动Web第二天:Flex伸缩布局-携程首页案例.zip

    此外,通过设置`flex-grow`, `flex-shrink`和`flex-basis`这三个Flex项目的属性,可以控制它们在可用空间中的扩展、收缩和基础大小。 总的来说,通过Flex布局,携程首页能够实现响应式设计,保证在不同分辨率和屏幕...

    flex-2.5.39.tar.gz

    标题中的"flex-2.5.39.tar.gz"是一个开源软件Flex的源代码压缩包,版本号为2.5.39。Flex是一个用于生成词法分析器(也称为扫描器或词法规则解析器)的工具,常用于处理语言和文本解析任务。它在各种软件开发项目中,...

    flex-tour-de-flex-component-explorer-1.2-308demo

    非常好DEMO参考,这个项目已经转到Apache名下了,最新的版本1.2,308个例子,已经全站打包,搜索:flex-tour-de-flex-component-explorer-1.2-308demo。开源代码http://flex.apache.org/download-tourdeflex.html

    flex布局-flex-layout-master.zip

    - `flex`:是`flex-grow`, `flex-shrink`和`flex-basis`的简写形式。 - `align-self`:允许单个Flex项独立设置其在交叉轴上的对齐方式,覆盖容器的`align-items`属性。 5. **Flex容器属性**:用于控制整个Flex...

Global site tag (gtag.js) - Google Analytics