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

Flash/Flex学习笔记(39):万有引力与粒子系统

阅读更多

万有引用公式:

其中G为万有引力常数


var numParticles:uint=50;//粒子总数

 
var G:Number=0.03;//万有引力常数

var particles:Array=new Array(numParticles);

var bounce:Number=-0.4;//边界反弹系统

 
//初始化

 
function init():void {


particles = new Array();

 
for (var i:uint = 0; i < numParticles; i++) {

var size:Number=Math.random()*12+3;

 
var particle:Ball=new Ball(size,Math.random()*0xffffff);

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


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

 
particle.mass=Math.PI * size * size;//质量与球截面积关联,即从视觉效果上看,个头越大,越重


addChild(particle);

 
particles.push(particle);


}

 
addEventListener(Event.ENTER_FRAME, EnterFrameHandler);

 
}

 
function EnterFrameHandler(event:Event):void {

 
for (var i:uint = 0; i < numParticles; i++) {


var particle:Ball=particles[i];

 
particle.x+=particle.vx;

 
particle.y+=particle.vy;

 
}

 
for (i=0; i < numParticles - 1; i++) {


var partA:Ball=particles[i];

 
for (var j:uint = i + 1; j < numParticles; j++) {

 
var partB:Ball=particles[j];

 
checkCollision(partA,partB);//检测碰撞

 
gravitate(partA, partB);//万有引力处理

 
}

 
checkWalls(partA);//边界检测

 
}

 
}

 
//万有引力处理

 
function gravitate(partA:Ball, partB:Ball):void {


var dx:Number=partB.x-partA.x;

 
var dy:Number=partB.y-partA.y;

 
var distSQ:Number=dx*dx+dy*dy;

 
var dist:Number=Math.sqrt(distSQ);

 
var force:Number=G*partA.mass*partB.mass/distSQ;//计算partA与partB的万有引力

 
var forceX:Number=force*dx/dist;//即:force * cos(a) --万有引力在x方向上的分量

 
var forceY:Number=force*dy/dist;//即:force * sin(a) --万有引力在y方向上的分量

partA.vx+=forceX/partA.mass;//牛顿定律a = F/m 在这里得到体现

 
partA.vy+=forceY/partA.mass;

 
partB.vx-=forceX/partB.mass;

 
partB.vy-=forceY/partB.mass;

 
}

 
//动量守恒的碰撞检测

 
function checkCollision(ball0:Ball, ball1:Ball):void {

 
var dx:Number=ball1.x-ball0.x;

 
var dy:Number=ball1.y-ball0.y;

 
var dist:Number=Math.sqrt(dx*dx+dy*dy);

 
if (dist<ball0.radius+ball1.radius) {

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

 
var sin:Number=Math.sin(angle);


var cos:Number=Math.cos(angle);

 
var pos0:Point=new Point(0,0);

 
var pos1:Point=rotate(dx,dy,sin,cos,true);

 
var vel0:Point=rotate(ball0.vx,ball0.vy,sin,cos,true);

 
var vel1:Point=rotate(ball1.vx,ball1.vy,sin,cos,true);

 
var vxTotal:Number=vel0.x-vel1.x;

vel0.x = ((ball0.mass - ball1.mass) * vel0.x + 2 * ball1.mass * vel1.x) / (ball0.mass + ball1.mass);

 
vel1.x=vxTotal+vel0.x;

 
var sumRadius:Number=ball0.radius+ball1.radius;

 
var overlap:Number=sumRadius-Math.abs(pos0.x-pos1.x);

 
var aRadio:Number=ball0.radius/sumRadius;

 
var bRadio:Number=ball1.radius/sumRadius;

if (overlap>0) {

 
if (pos0.x>pos1.x) {


pos0.x+=overlap*aRadio;

 
pos1.x-=overlap*bRadio;

 
} else {

 
pos0.x-=overlap*aRadio;

 
pos1.x+=overlap*bRadio;


}

 
}

 
var pos0F:Object=rotate(pos0.x,pos0.y,sin,cos,false);

 
var pos1F:Object=rotate(pos1.x,pos1.y,sin,cos,false);

 
ball1.x=ball0.x+pos1F.x;


ball1.y=ball0.y+pos1F.y;

 
ball0.x=ball0.x+pos0F.x;

 
ball0.y=ball0.y+pos0F.y;

 
var vel0F:Object=rotate(vel0.x,vel0.y,sin,cos,false);


var vel1F:Object=rotate(vel1.x,vel1.y,sin,cos,false);

 
ball0.vx=vel0F.x;

 
ball0.vy=vel0F.y;


ball1.vx=vel1F.x;

 
ball1.vy=vel1F.y;

 
}

}

 
//坐标旋转辅助方法

 
function rotate(x:Number, y:Number, sin:Number, cos:Number, reverse:Boolean):Point {

 
var result:Point = new Point();

 
if (reverse) {

 
result.x=x*cos+y*sin;

 
result.y=y*cos-x*sin;

 
} else {

 
result.x=x*cos-y*sin;


result.y=y*cos+x*sin;


}

 
return result;

 
}

 
//舞台边界检测  

 
function checkWalls(b:Ball) {

 
if (b.x<b.radius) {


b.x=b.radius;

 
b.vx*=bounce;

} else if (b.x>stage.stageWidth-b.radius) {


b.x=stage.stageWidth-b.radius;


b.vx*=bounce;

 
}

 
if (b.y<b.radius) {

 
b.y=b.radius;

 
b.vy*=bounce;

} else if (b.y>stage.stageHeight-b.radius) {

 
b.y=stage.stageHeight-b.radius;

 
b.vy*=bounce;

 
}

}


init();

 
btnReset.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);


function MouseDownHandler(e:MouseEvent):void {


removeEventListener(Event.ENTER_FRAME, EnterFrameHandler);

 
for (var i:uint = 0; i < numParticles; i++) {

var particle:Ball=particles[i];


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

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

 
particle.vx=0;

 
particle.vy=0;

 
}

 
addEventListener(Event.ENTER_FRAME, EnterFrameHandler);

 
}

代码虽然很长,但是其中有很多都是上一篇里封装好的方法直接复制过来的,应该不难理解

再来模拟一下地球绕着太阳转:

var numParticles:uint=2;//粒子总数


var G:Number=0.03;//万有引力常数

 
var particles:Array=new Array(numParticles);

 
var i:Number=0;

//初始化

 
function init():void {

 
particles = new Array(); 

 
var sun:Ball = new Ball(30, 0xff0000); 

 
sun.x = stage.stageWidth / 2

 
sun.y = stage.stageHeight / 2

 
sun.mass = 900000

 
addChild(sun); 

 
particles.push(sun); 

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

 
planet.x = stage.stageWidth / 2 + 200

 
planet.y = stage.stageHeight / 2

 
planet.vy = 8

 
planet.mass = 1


addChild(planet); 


particles.push(planet); 

 
addEventListener(Event.ENTER_FRAME, EnterFrameHandler);


graphics.lineStyle(1,0xdddddd);

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

 
}


function EnterFrameHandler(event:Event):void {

 
for (var i:uint = 0; i < numParticles; i++) {


var particle:Ball=particles[i];

 
particle.x+=particle.vx;

 
particle.y+=particle.vy;


}

 
for (i=0; i < numParticles - 1; i++) {


var partA:Ball=particles[i];


for (var j:uint = i + 1; j < numParticles; j++) {


var partB:Ball=particles[j];            

 
gravitate(partA, partB);//万有引力处理


}       

 
}


}

 
//万有引力处理  
function gravitate(partA:Ball, partB:Ball):void {   

 
var dx:Number=partB.x-partA.x;

 
var dy:Number=partB.y-partA.y;

 
var distSQ:Number=dx*dx+dy*dy;

 
var dist:Number=Math.sqrt(distSQ);

 
var force:Number=G*partA.mass*partB.mass/distSQ;//计算partA与partB的万有引力


var forceX:Number=force*dx/dist;//即:force * cos(a) --万有引力在x方向上的分量

 
var forceY:Number=force*dy/dist;//即:force * sin(a) --万有引力在y方向上的分量

 
/*

 
partA.vx+=forceX/partA.mass;//牛顿定律a = F/m 在这里得到体现
partA.vy+=forceY/partA.mass;

 
*/

 
partB.vx-=forceX/partB.mass;

 
partB.vy-=forceY/partB.mass;

 
trace(i);

 
if (i<=1000){

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


i++;        

 
}

 
else{

 
graphics.clear();


graphics.lineStyle(1,0xdddddd);


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


i=0;

 
}


}

 
init();

代码就是在第一段的基础上修改的,可以看到在"远日点"速度较慢(因为距离越远,万有引力越小,对应的加速度也较小),在"近日点"速度较快(距离越近,万有引力越大,对应的加速度也较大)

节点花园NodeGarden:

为啥叫这个名字,我也说不上来,反正ActionScript3.0 in Animation一书的作者是这么叫的。

var particles:Array;

 
var numParticles:uint=60;


var minDist:Number=100;

 
var springAmount:Number=0.0004;

 
var friction:Number = 0.9995;


function init():void {

 
stage.scaleMode=StageScaleMode.NO_SCALE;


stage.align=StageAlign.TOP_LEFT;

 
particles = new Array();


for (var i:uint = 0; i < numParticles; i++) {

 
var particle:Ball=new Ball(Math.random()*3+2,0xffffff);

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

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

 
particle.vx=Math.random()*6-3;


particle.vy=Math.random()*6-3;

 
addChild(particle);


particles.push(particle);

}

 
addEventListener(Event.ENTER_FRAME, EnterFrameHandler);

}

 
function EnterFrameHandler(event:Event):void {

 
graphics.clear();

 
for (var i:uint = 0; i < numParticles; i++) {

 
var particle:Ball=particles[i];

 
particle.x+=particle.vx;

 
particle.y+=particle.vy;

 
//屏幕环绕处理


if (particle.x>stage.stageWidth) {

 
particle.x=0;

 
} else if (particle.x < 0) {


particle.x=stage.stageWidth;

 
}


if (particle.y>stage.stageHeight) {

 
particle.y=0;

 
} else if (particle.y < 0) {

 
particle.y=stage.stageHeight;

 
}

 
}


for (i=0; i < numParticles - 1; i++) {

 
var partA:Ball=particles[i];

 
for (var j:uint = i + 1; j < numParticles; j++) {


var partB:Ball=particles[j];

 
spring(partA, partB);//每个粒子均与其它粒子进行弹性运动处理

 
}   

 
partA.vx *= friction;


partA.vy *= friction;


}

 
}


function spring(partA:Ball, partB:Ball):void {


var dx:Number=partB.x-partA.x;

 
var dy:Number=partB.y-partA.y;


var dist:Number=Math.sqrt(dx*dx+dy*dy);

 
if (dist<minDist) {      


graphics.lineStyle(1, 0x00ff00, 1 - dist / minDist);//注意这里的透明度设置:二球越来越近时,线条越来越明显,距离越来越远时,线条越来越淡

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


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

 
//类似弹性运动处理

 
var ax:Number=dx*springAmount;

 
var ay:Number=dy*springAmount;

 
//A球加速

 
partA.vx+=ax;

 
partA.vy+=ay;

 
//B球减速

 
partB.vx-=ax;

 
partB.vy-=ay;


//一个球越来越快,一个球越来越慢,所以会不断拉近(当然:前提是在有效距离内)

 
}

 
}

 
init();

关于这个效果,建议初次接触的同学们,先回顾一下弹性运动:Flash/Flex学习笔记(40):弹性运动续--弹簧

可以稍加改进,加入质量因素:

var particles:Array;

 
var numParticles:uint=30;


var minDist:Number=120;


var springAmount:Number=0.03;

 
var friction:Number = 0.998;

 
var stageHeight:Number = stage.stageHeight;


var stageWidth:Number = stage.stageWidth;

 
function init():void {

 
stage.scaleMode=StageScaleMode.NO_SCALE;

stage.align=StageAlign.TOP_LEFT;

 
particles = new Array();

 
for (var i:uint = 0; i < numParticles; i++) {


var particle:Ball=new Ball(Math.random()*5+2,0xffffff);

 
particle.x=Math.random()*stageWidth;

 
particle.y=Math.random()*stageHeight;


particle.vx=Math.random()*6-3;

 
particle.vy=Math.random()*6-3;

 
particle.mass = Math.PI*particle.radius*particle.radius;//加入质量


addChild(particle);

particles.push(particle);

 
 
addEventListener(Event.ENTER_FRAME, EnterFrameHandler);

 
stage.addEventListener(MouseEvent.MOUSE_MOVE,MouseMoveHandler);  
}

 
//鼠标互动  
function MouseMoveHandler(e:MouseEvent):void{   

 
var dx:Number = mouseX - stageWidth/2;

 
var dy:Number = mouseY - stageHeight/2;     


for (var i:uint = 0; i < numParticles; i++) {

 
var b:Ball=particles[i];        


b.x -= dx/b.mass;


b.y -= dy/b.mass;

 
}   


}


function EnterFrameHandler(e:Event):void {


graphics.clear();

for (var i:uint = 0; i < numParticles; i++) {

 
var particle:Ball=particles[i];


particle.x+=particle.vx;

 
particle.y+=particle.vy;        

 
//屏幕环绕处理

 
if (particle.x>stageWidth) {

 
particle.x=0;

 
} else if (particle.x < 0) {


particle.x=stageWidth;

 
}

 
if (particle.y>stageHeight) {


particle.y=0;

 
} else if (particle.y < 0) {

 
particle.y=stageHeight;

 
}


}

 
for (i=0; i < numParticles - 1; i++) {

 
var partA:Ball=particles[i];

 
for (var j:uint = i + 1; j < numParticles; j++) {


var partB:Ball=particles[j];

spring(partA, partB);//每个粒子均与其它粒子进行弹性运动处理

 
}   

 
partA.vx *= friction;

 
partA.vy *= friction;

 
}

 
}

 
function spring(partA:Ball, partB:Ball):void {

 
var dx:Number=partB.x-partA.x;

 
var dy:Number=partB.y-partA.y;

 
var dist:Number=Math.sqrt(dx*dx+dy*dy);

 
if (dist<minDist) {      

 
graphics.lineStyle(1, 0x00ff00, 1 - dist / minDist);//注意这里的透明度设置:二球越来越近时,线条越来越明显,距离越来越远时,线条越来越淡

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

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

 
//类似弹性运动处理

 
var ax:Number=dx*springAmount;

 
var ay:Number=dy*springAmount;


//A球加速

 
partA.vx+=ax/partA.mass;

 
partA.vy+=ay/partA.mass;

 
//B球减速

 
partB.vx-=ax/partB.mass;

 
partB.vy-=ay/partB.mass;

 
//一个球越来越快,一个球越来越慢,所以会不断拉近(当然:前提是在有效距离内)     

 
}   

 
}

 
init();

下面这种效果也是很多Flash网站上都有的,效果还不错,而且原理也很简单:
var ballCount:uint = 100;

 
var friction:Number = 0.95;

 
var massRadio = 0.005;

 
var arrBall:Array = new Array(ballCount);


var stageWidth:Number = stage.stageWidth;

 
var stageHeight:Number = stage.stageHeight;


for(var i:uint=0;i<ballCount;i++){

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

 
arrBall[i].x = Math.random()*stageWidth;

 
arrBall[i].y = Math.random()*stageHeight;

 
arrBall[i].mass = massRadio * arrBall[i].radius;

 
addChild(arrBall[i]);

 
}

 
stage.addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

 
stage.addEventListener(MouseEvent.MOUSE_MOVE,MouseMoveHandler);

 
function EnterFrameHandler(e:Event):void{       

 
for(var i:uint=0;i<ballCount;i++){

 
var b:Ball = arrBall[i];        

 
b.vx *=friction;

 
b.vy *=friction;

 
b.x += b.vx;

 
b.y += b.vy;

 
//屏幕环绕处理

 
if (b.x>stageWidth+b.radius){

 
b.x=-b.radius;

 
} else if (b.x<-b.radius){

 
b.x = stageWidth+b.radius;

 
}       

 
if (b.y>stageHeight+b.radius){

 
b.y=-b.radius;

 
}

 
else if (b.y<-b.radius){

 
b.y = stageHeight+b.radius;

 
}

 
}       


}

 
function MouseMoveHandler(e:MouseEvent):void{   

 
var CenterX:Number = 0.5*stageWidth;


var CenterY:Number = 0.5*stageHeight;

 
var dx:Number = mouseX - CenterX;

 
var dy:Number = mouseY - CenterY;   

 
for(var i:uint=0;i<ballCount;i++){

 
var b:Ball = arrBall[i];

 
//设置速度


b.vx = -dx*b.mass;

 
b.vy = -dy*b.mass;      


}       


}

下面这个是它的变种:

分享到:
评论

相关推荐

    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应用研究

    flash/flex画曲线,绘图板

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

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

    语言:C ++许可证:BSD-3代码质量:A + https://lgtm.com/projects/g/Genivia/RE-flex/context:cpp文档:https://www.genivia.com/doc/reflex/html /index.html存储库:https://github.com/Genivia/RE-flex更改日志...

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

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

    FDT-flash/flex devtoolkit for eclipse.

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

    flash/flex 的aqua皮肤

    在IT行业中,Flash/Flex是一种广泛使用的开发工具,主要用于创建交互式、富媒体的Web应用程序。Flex是基于ActionScript和MXML的开放源代码框架,它允许开发者构建可自定义的用户界面,而Flash则是其背后的动画和...

    FLEX安装方法 集成到eclipse中

    FLEX 安装方法 集成到 eclipse 中 ...* 汉化 FLEX 尤其是 FLEX/AIR 方面的中文资料 * 原创的关于 FLEX 的博客:http://liguoliang.com/ * Adobe 公司 FLEX 主页:http://www.adobe.com/cn/products/flex/

    Flex:登录

    标题“Flex:登录”指的是使用Adobe Flex技术实现用户登录功能的一种方法。Flex是Adobe公司推出的一款基于ActionScript的开源框架,主要用于...压缩包中的"Flex Login"可能包含示例代码或项目结构,供读者学习和参考。

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

    Flex Builder(现已被Adobe Flash Builder取代)是一个集成开发环境,提供了代码提示、调试和项目管理等功能,使得开发更加高效。 3. **Flex组件库**:Flex提供了丰富的预定义组件,如Button、Label、Canvas等,可...

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

    RTMP(Real-Time Messaging Protocol)...通过学习和理解源代码,你可以深入了解RTMP协议的实现细节,以及FLEX如何与服务器和客户端进行交互。这对于想要从事音视频直播开发的人员来说,是一个宝贵的实践和学习资源。

    解决flash/flex/as3 访问中文域名时的流错误示例

    在《潮汕IT男》网站的文章《解决flash/flex/as3 访问中文域名时的流错误》中,作者陈林生提供了详细的步骤和代码示例,帮助开发者理解和解决这个问题。文章地址是:[http://chenlinsheng.com/?p=990]...

    FLEX学习笔记

    《FLEX学习笔记》 FLEX,全称为Flex Builder,是由Adobe公司开发的一款基于MXML和ActionScript的开源框架,用于构建富互联网应用程序(RIA)。它允许开发者创建具有交互性、响应性和丰富用户体验的Web应用。FLEX的...

    Flex学习笔记.rar

    1. **Flex概述**:介绍Flex技术的基本概念,包括它的历史、目标和应用领域,以及它与Flash Player和Adobe AIR的关系。 2. **Flex开发环境**:可能会讲解如何安装和配置Flex Builder或IntelliJ IDEA等开发工具,以及...

    flex开源项目介绍.doc

    Flex开源项目介绍 Flex是一种用于构建富互联网应用程序(RIA)的开源框架,它基于ActionScript 3(AS3)编程语言和MXML标记语言。这些开源项目为开发者提供了丰富的组件库、工具和框架,帮助他们扩展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

    Flex与Java的交互

    Flex与Java的交互是跨平台应用开发中的常见技术组合,允许前端用户界面(UI)与后端业务逻辑进行高效沟通。在本文中,我们将深入探讨如何使用Flex 4与Java进行通信,并通过三种不同的方法实现这一目标:RemoteObject...

    flex actionscript学习笔记

    Flex ActionScript 学习笔记是关于使用Adobe Flex技术并结合ActionScript 3.0进行开发的知识总结。ActionScript 3.0是随着Flash CS3一起推出的一种强大的编程语言,相较于之前的ActionScript版本,它有着显著的提升...

Global site tag (gtag.js) - Google Analytics