打印

[编程] AS3做的“细胞”-碰撞检测和运动方程的应用

AS3做的一个碰撞练习,做完之后发现碰撞方式既不是刚体也不是柔体(其实是算法不够精确),挺像细胞的。帖出来大家娱乐一下
http://www.parishine.net/lab/cell/

[ 本帖最后由 adamblue 于 2006-12-27 11:14 编辑 ]
附件: 您所在的用户组无法下载或查看附件,您需要注册/登录后才能查看!
很好的东西,如果能把思路介绍一下就更好了
珍惜生命,远离IT
呵呵,真的很像细胞
黑羽翔天◎足下八邦
欢迎来我的博客 :)
www.kingda.org  (AS3教程)
是我的第一个AS3练习,也是在深海蓝等兄弟的帮助下写的,思路是这样的,总共有三个文件:
一个.fla文件
一个Cell自定义类文件
一个CellDocument自定义类文件

.fla文件中有一个mc,是一个与Cell类关联的圆形。
Cell类中用Timer每50毫秒做一次运算,运算用三个函数实现三个功能:1 细胞的运动;2 碰到舞台边缘后反弹;3 与其他球体碰撞(hitTestObject())后反弹。
CellDocument是文件类,由它向舞台添加若干个Cell类的实例。

因为碰撞运算的时候,考虑到运算量比较大,做了一些简化,比如假设球体重量都一样,加之运算的频率也不是很高,所以出现了粘滞现象。

Cell类:
package classes{
       import flash.display.Sprite;
       import flash.events.MouseEvent;
       import flash.utils.Timer;
       import flash.events.TimerEvent;
       public class Cell extends Sprite{
              var Y:int;
              var limitT:uint=0;
              var limitB:uint;
              var limitL:uint=0;
              var limitR:uint;
              var document:CellDocument;
              var id:uint;
              var va:Object=new Object();
              var vf:Object=new Object();
              
              public function Cell(){
                     this.buttonMode=true;
                     trace("Ball created");
                     var myTimer:Timer = new Timer(50, 0);
            myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
            myTimer.start();
              }
              public function timerHandler(event:TimerEvent):void {
                     limitB=this.stage.stageHeight-this.height;
                     limitR=this.stage.stageWidth-this.width;
                     myMove();
              }
              public function myMove(){
                     if (this.y>limitB || this.y<limitT) {
                            this.y-=va.y;
                            va.y=-va.y;
                            do{
                                   va.y+=(Math.round(Math.random()*2)-1)
                            }while(va.y==0 || va.y>5 || va.y<-5)
                     }
                     if (this.x>limitR || this.x<limitL) {
                            this.x-=va.x;
                            va.x=-va.x;
                            do{
                                   va.x+=(Math.round(Math.random()*2)-1)
                            }while(va.x==0 || va.x>5 || va.x<-5)
                     }
                     this.x += va.x;
                     this.y += va.y;
                     
                     for(i=0;i<20;i++){
                            if(i!=this.id && this.hitTestObject(getCell("cell_"+i))){
                                   collision(va,getCell("cell_"+i).va,vf,getCell("cell_"+i).vf,this,getCell("cell_"+i));
                                   va=vf;
                                   getCell("cell_"+i).va=getCell("cell_"+i).vf;
                            }
                     }
              }
              public function getCell(cellname){
                     return stage.getChildByName(cellname);
              }

              public function collision(v1a, v2a, v1f, v2f, m1, m2){
                     var sx = m1.x - m2.x ;
                     var sy = m1.y - m2.y ;
                     var s1x = sx / Math.sqrt(sx*sx + sy*sy) ;
                     var s1y = sy / Math.sqrt(sx*sx + sy*sy) ;
                     var tx = -sy ;
                     var ty = sx ;
                     var t1x = tx / Math.sqrt(tx*tx + ty*ty) ;
                     var t1y = ty / Math.sqrt(tx*tx + ty*ty) ;
                     var v1s = v1a.x * s1x + v1a.y * s1y ;
                     var v1t = v1a.x * t1x + v1a.y * t1y ;
                     var v2s = v2a.x * s1x + v2a.y * s1y ;
                     var v2t = v2a.x * t1x + v2a.y * t1y ;
                     var v1sf = v2s ;
                     var v2sf = v1s ;
                     var nsx = v1sf * s1x ;
                     var nsy = v1sf * s1y ;
                     var ntx = v1t * t1x ;
                     var nty = v1t * t1y ;
                     v1f.x = nsx + ntx ;
                     v1f.y = nsy + nty ;
                     nsx = v2sf * s1x ;
                     nsy = v2sf * s1y ;
                     ntx = v2t * t1x ;
                     nty = v2t * t1y ;
                     v2f.x = nsx + ntx ;
                     v2f.y = nsy + nty ;
              }// end of function
       }
}


CellDocument类:
package classes{
    import flash.display.Sprite;
       public class CellDocument extends Sprite{
              var cell:Cell;
              public function CellDocument(){
                     for(i=0;i<20;i++){
                            cell=new Cell();
                            cell.x=(this.stage.stageWidth-this.width-200)*Math.random()+100;
                            cell.y=(this.stage.stageWidth-this.height-200)*Math.random()+50;
                            var magnify=Math.random();
                            cell.alpha=cell.scaleX=cell.scaleY=magnify*0.5+1;
                            do{
                                   var tempSpeed=Math.round(magnify*3+1)*(Math.round(Math.random()*2)-1);
                            }while(tempSpeed==0);
                            cell.va.x=cell.va.y=tempSpeed;
                            cell.id=i;
                            cell.name = "cell_" + i;
                            stage.addChild(cell);
                     }
              }
       }
}

TOP

还在为头像烦恼?还在为不能关注好友动态烦忧?快来蓝色理想家园吧!
==~~ 天啊 for循环来检测啊 万一球很多不是机器要卡死

不知道有没有其他方法

TOP

引用:
原帖由 kolou 于 2006-12-26 23:26 发表
==~~ 天啊 for循环来检测啊 万一球很多不是机器要卡死

不知道有没有其他方法
现在CPU的占用率为20-30%(3GHz,1G内存)。
我也想知道:除了用for遍历之外还有没有别的方法? 如果有更高效的方法,对做游戏一定有帮助。

TOP

哇。。不错呢。。可惜就是太耗资源了

TOP

可以把它放到类的层面上考虑一下碰撞
一个细胞 是一个对象,有自己的位置和直径
有自己的碰撞检测方法
不行再加一个消息监听
经典
确实 有 经典!

主页:
flash59.it50.net
FLASH论坛:
在首页里。

TOP

是一样的:每个细胞检测是否与其他所有细胞发生碰撞

TOP

提点缺点哦!
当两个小圆成角度(比如它俩连起来与X轴成45度)碰撞时只是hitTest圆所在mc 的矩形,而不是圆本身.
可试试用BitmapData

TOP