KCDDP ADV综合创作站 » 技术发布区 » 在空中旋转飞扬的米粒们......


2007-6-18 14:16 karryngai
在空中旋转飞扬的米粒们......

此东西是个恐怖的存在(至少个人这样认为),单是debug,偶就用了不少时间,主要是变量太多了
此东西如果粒子数设计得太多的话,运作起来会很卡的,因为旋转这个东西很费记忆体


此东西是用来实现粒子一边旋转一边从屏幕的不同角度飞出来的效果
@rflying storage=leaf num=10 angle=30 angleoffset=30 speedoffset=20 speed=5 accel=0.05 rspeedoffset=12 rspeed=1 raccel=0.03 p=255 pspeedoffset=20 pspeed=15 paccel=5 s=1 sspeedoffset=0 sspeed=0 saccel=0 totaltime=10000 interval=50 appearprob=0.01 index=3000000
        keepaccel=false keepsaccel=false
storage                图像名,如storage=leaf,指的是leaf_0.png,leaf_1.png,leaf2.png.....一组的图像,程序会随机抽取它们中的一个作为粒子
num                出现的粒子数目,其实粒子数目是2*num,因为里面设置了两组粒子,用来解决角度的问题,预设是10,设置20个电脑已经开始卡了= =

angle                粒子飞出来的角度,angle=30就是指粒子从右上角向下走30度的位置飞出,预设是0
angleoffset        这个东西能打乱各个粒子飞出来的角度,是原来角度上的偏移值,如angleoffset=30,就是指粒子有可能从30-30=0的角度或30+30=60的角度飞出来,设置得很大的话,粒子的混乱性越明显,个人觉得这是个好东西,预设是0

speedoffset        速度的偏移值,和angleoffset的道理一样,让粒子出现速度上的不同,预设是0
speed                粒子的飞行速度,预设是20
accel                加速度,预设是0.01

rspeedoffset        旋转速度的偏移值,道理同上,预设是0
rspeed                旋转速度,预设是0
raccel                旋转的加速度,预设是0

p                初始透明度
pspeedoffset        透明度的偏移值,预设是0
pspeed                透明度,预设是255
paccel                透明度变化的加速度,预设是0

s                初始形状
sspeedoffset        形状变化的偏移值,预设是0
sspeed                形状变化的速度,如sspeed=1.5,就是指在一个单位时间内形状扩大为原来的1.5倍,预设是0
saccel                形状变化的加速度

totaltime        总飞行的时间,不设置的话,就会无穷时间地飞行,预设是void,也就是不停地飞行
interval        变换的单位时间,预设是50,最好不要改动

appearprob        出现的概率,指粒子不会全部同时出现,而是按照一定的概率出现,1的话就是必然出现,预设是0.1

index                粒子所在层的absolute,预设是2000000

keepaccel        是否让加速度不停地进行下去,为false时,粒子回到屏幕边缘时速度会变回原来的,如果设置为true,速度就不会变回原状
                注意因为此程序为省资源,并没有使用补间的方式写,所以速度过快的话,也就是说粒子跳得很快,最后一跳就能跳到边缘,所以就看不见了
                不推荐使用此功能,预设是false
keepsaccel         是否让形状变化不停地进下去,和keepaccel道理相同,预设是false

@stoprflying
强制停止飞行,事实设定了totaltime后,粒子就会在那时间后消失在看不见的地方,绝对不会有停滞的画面出现
所以如果没有什么必要,可以不使用stopflying,占用内存会自动清除

@leafrflying
直接贴封装方式
@macro name=leafrflying
@rflying storage=%storage|leaf num=%num angle=%angle|30.0 angleoffset=%angleoffset|20.0 speedoffset=%speedoffset|20.0 speed=%speed|5.0 accel=%accel|0.05 rspeedoffset=%rspeedoffset|12.0 rspeed=%rspeed|1.0 raccel=%raccel totaltime=%totaltime|20000 appearprob=%appearprob
@endmacro
模拟的是树叶从30度角的地方飞出来旋转的情形

@starrflying
直接贴封装方式
@macro name=starrflying
@rflying storage=%storage|star num=%num angle=%angle|30.0 angleoffset=%angleoffset|20.0 speedoffset=%speedoffset|20.0 speed=%speed|5.0 accel=%accel|0.05 pspeedoffset=%pspeedoffset|60.0 pspeed=%pspeed|40.0 paccel=%paccel totaltime=%totaltime|20000 appearprob=%appearprob
@endmacro
模拟的是星星一闪一闪地移动的情形,建议不要用这个,因为这个没有使用旋转,实在没有必要去浪费内存空间

@rjump
直接贴封装方式
@macro name=rjump
@rflying storage=%storage|ball num=%num angle=%angle|-90  speedoffset=%speedoffset|30.0 speed=%speed|10.0 accel=%accel|-1 rspeedoffset=%rspeedoffset|12.0 rspeed=%rspeed|1.0 paccel=%paccel totaltime=%totaltime|20000 appearprob=%appearprob
@endmacro
摸拟的是球旋转地从屏幕下部拥出来,减速跳出最高处后又加速落下来的情形,偶最喜欢这个了,因为太漂亮了,旋转能带出动态感


这个东西不好的地方是粒子数不能设计得太多,否则电脑随时会挂掉,50个粒子(25*2)大概是极限了
至于等比放大和缩小的作用,偶还想不出什么比较漂亮的粒子移动画面,大家可以发挥想象力去弄这个东西


算法上是使用copyaffine和物理上的加速度实现的,因为使用了copyaffine,所以速度会很慢,算法没有采用zoomrot的,原因是那个东西,减速减到0后就不能再减了

[[i] 本帖最后由 karryngai 于 2007-6-22 19:37 编辑 [/i]]

2007-6-18 14:16 karryngai
[code]
@if exp="typeof(global.skyrotateflying_object)=='undefined'"
@iscript

class RotateFlyingGrain{
        var window,owner;
        var cx,cy;
        var sx,sy;
        var dx,dy;
        var p,s;
        var speed,rspeed,pspeed,sspeed;       
        var accel,raccel,paccel,saccel;
        var templayer;
        var targetlayer;
        var a00,a01,a10,a11,ax,ay;
        var piccount;
        var angle;
        var scale=0,pscale=0,sscale=0;
        var appear;
        var k=1;
        var east=false,south=false,west=false,north=false;
        var movedp;
        var angle;
        var vanishing,hasbeencounted;

        function RotateFlyingGrain(window,owner){
                this.window=window;
                this.owner=owner;
        }

        function setOption(elm){
                piccount=0;
                appear=false;
                vanishing=false;
                hasbeencounted=false;

                if(elm.storage!==void){
                        for(var i=0;;i++){
                                if(Storages.isExistentStorage(elm.storage+"_"+i+".png"))
                                        piccount++;
                                else
                                        break;
                        }
                }
                else{
                        for(var i=0;;i++){
                                if(Storages.isExistentStorage("flying_object_"+i+".png"))
                                        piccount++;
                                else
                                        break;
                        }
                }

                templayer=new Layer(window,window.primaryLayer);
                if(elm.storage!==void)
                        templayer.loadImages(elm.storage+"_"+intrandom(0,piccount-1)+".png");
                else
                        templayer.loadImages("flying_object_"+intrandom(0,piccount-1)+".png");

                targetlayer=new Layer(window,window.primaryLayer);
                targetlayer.setPos(0,0,window.primaryLayer.width,window.primaryLayer.height);

                if(elm.index!==void)
                        targetlayer.absolute=elm.index;
                else
                        targetlayer.absolute=2000000-1;

                if(east){
                        sx=window.primaryLayer.width;
                        sy=window.primaryLayer.height*Math.random();
                }
                if(south){
                        sx=window.primaryLayer.width*Math.random();
                        sy=window.primaryLayer.height;
                }
                if(west){
                        sx=-templayer.imageWidth;
                        sy=window.primaryLayer.height*Math.random();
                }
                if(north){
                        sx=window.primaryLayer.width*Math.random();
                        sy=-templayer.imageHeight;
                }

                cx=templayer.imageWidth/2;
                cy=templayer.imageHeight/2;               

                speed=+elm.speed+elm.speedoffset*Math.random();
                accel=+elm.accel;

                rspeed=+elm.rspeed+elm.rspeedoffset*Math.random();
                raccel=+elm.raccel;

                p=+elm.p;               
                movedp=p;
                pspeed=+elm.pspeed+elm.pspeedoffset*Math.random();
                paccel=+elm.paccel;

                s=+elm.s;
                sspeed=+elm.sspeed+elm.sspeedoffset*Math.random();
                saccel=+elm.saccel;

                angle=+elm.angle;

                targetlayer.visible=true;
                targetlayer.face = dfAlpha;
                targetlayer.type = ltAlpha;
        }

        function setPosition(){
                if(vanishing && scale==0){
                         targetlayer.opacity=0;
                         if(!hasbeencounted) owner.vanishcount++,hasbeencounted=true;
                         return;
                }
                var sc=scale*(scale-1)/2;
                var moveds=s+sspeed*sscale+sscale*(sscale-1)/2.0*saccel;
                var movedr=(rspeed*scale+sc*raccel)/180.0*Math.PI;
               
                var movedx=sx+(speed*scale+sc*accel)*Math.cos(angle/180*Math.PI);
                var movedy=sy+(speed*scale+sc*accel)*Math.sin(angle/180*Math.PI);               
               
                if(owner.totaltime<0 && scale==0){
                        stopMove();
                        return;
                }
               
                if((movedx>window.primaryLayer.width) || (movedx<-templayer.imageWidth) || (movedy>window.primaryLayer.height) || (movedy<-templayer.imageHeight)){
                        if(east)
                                sy=window.primaryLayer.height*Math.random();
               
                        if(south)
                                sx=window.primaryLayer.width*Math.random();
                        if(west)
                                sy=window.primaryLayer.height*Math.random();
                        if(north)
                                sx=window.primaryLayer.width*Math.random();
                        scale=0 if !owner.keepaccel;
                        sscale=0 if !owner.keepsaccel;
                }
                else{
                        scale++ if !owner.keepaccel;
                        sscale++ if !owner.keepsaccel;
                }
                if(owner.keepaccel) scale++;
                if(owner.keepsaccel) sscale++;

                a00=moveds*Math.cos(movedr);
                a01=moveds*Math.sin(movedr);
                a10=-moveds*Math.sin(movedr);
                a11=moveds*Math.cos(movedr);

                ax=a00*-cx+a01*-cy+movedx+cx;
                ay=a10*-cx+a11*-cy+movedy+cy;
                       
                targetlayer.fillRect(0,0,targetlayer.imageWidth,targetlayer.imageHeight,0);
                targetlayer.affineCopy(templayer,0,0,templayer.imageWidth,templayer.imageHeight,true,a00,a10,a01,a11,ax,ay,stNearest);
        }

        function setOpacity(){
                if(vanishing && scale==0){
                         targetlayer.opacity=0;
                         return;
                }

                if(owner.totaltime<0 && scale==0){
                        return;
                }
               
                movedp+=int(k*pspeed+k*pscale*paccel);
                if(movedp>255){
                        movedp=255-movedp%256;
                        k=-1;
                }
                if(movedp<0){
                        movedp=-movedp%256;
                        k=1;
                }
               
                targetlayer.opacity=movedp;
                pscale++;
        }

        function stopMove(){
                invalidate templayer if templayer!==void;
                invalidate targetlayer if targetlayer!==void;
                templayer=targetlayer=void;
        }
}

class SkyRotateFlying extends KAGPlugin{
        var window;       
        var num;
        var flyinggrainx=[];
        var flyinggrainy=[];
        var dic=%[];
        var angleoffset;
        var interval;
        var timer,totaltime;
        var appearprob;
        var vanishcount;
        var keepaccel,keepsaccel;

        function SkyRotateFlying(window){
                super.KAGPlugin();
                this.window=window;
        }

        function setOption(elm){
                vanishcount=0;       
                       
                if(elm.keepaccel!==void)
                        keepaccel=elm.keepaccel;
                else
                        keepaccel=false;

                if(elm.keepsaccel!==void)
                        keepsaccel=elm.keepsaccel;
                else
                        keepsaccel=false;

                if(elm.storage!==void)
                        dic.storage=elm.storage;

                if(elm.index!==void)
                        dic.index=elm.index;

                if(elm.appearprob!==void)
                        appearprob=+elm.appearprob;
                else
                        appearprob=0.1;

                if(elm.interval!==void)
                        interval=+elm.interval;
                else
                        interval=50;

                if(elm.speed!==void)
                        dic.speed=+elm.speed;
                else
                        dic.speed=20;

                if(elm.speedoffset!==void)
                        dic.speedoffset=+elm.speedoffset;
                else
                        dic.speedoffset=0;

                if(elm.accel!==void)
                        dic.accel=+elm.accel;
                else
                        dic.accel=0.01;

                if(elm.rspeed!==void)
                        dic.rspeed=+elm.rspeed;
                else
                        dic.rspeed=0;

                if(elm.rspeedoffset!==void)
                        dic.rspeedoffset=+elm.rspeedoffset;
                else
                        dic.rspeedoffset=0;

                if(elm.raccel!==void)
                        dic.raccel=+elm.raccel;
                else
                        dic.raccel=0;

                if(elm.p!==void)
                        dic.p=+elm.p;
                else
                        dic.p=255;

                if(elm.pspeedoffset!==void)
                        dic.pspeedoffset=+elm.pspeedoffset;
                else
                        dic.pspeedoffset=0;

                if(elm.pspeed!==void)
                        dic.pspeed=+elm.pspeed;
                else
                        dic.pspeed=0;

                if(elm.paccel!==void)
                        dic.paccel=+elm.paccel;
                else
                        dic.paccel=0;

                if(elm.s!==void)
                        dic.s=+elm.s;
                else
                        dic.s=1;
               
                if(elm.sspeed!==void)
                        dic.sspeed=+elm.sspeed;
                else
                        dic.sspeed=0;

                if(elm.sspeedoffset!==void)
                        dic.sspeedoffset=+elm.sspeedoffset;
                else
                        dic.sspeedoffset=0;
               
                if(elm.totaltime!==void)
                        totaltime=+elm.totaltime;
                else
                        totaltime=void;

                if(elm.angleoffset!==void)
                        angleoffset=+elm.angleoffset;
                else
                        angleoffset=0;
        }

        function startFlying(elm){
                var angle;

                if(elm.num!==void)
                        num=+elm.num;
                else
                        num=10;
                for(var i=0;i<num;i++){
                        flyinggrainx[i]=new RotateFlyingGrain(window,this);
                        flyinggrainy[i]=new RotateFlyingGrain(window,this);

                        setOption(elm);
                        if(elm.angle!==void)
                                angle=int(+elm.angle+(Math.random()-0.5)*2*angleoffset)%360;
                        else
                                angle=int((Math.random()-0.5)*2*angleoffset)%360;

                        if(angle<0)
                                angle+=360;

                        dic.angle=angle;

                        if(angle==0){
                                flyinggrainx[i].west=true;
                                flyinggrainy[i].west=true;
                        }
                        if(angle>0 && angle<90){
                                flyinggrainx[i].west=true;
                                flyinggrainy[i].north=true;
                        }
                        if(angle==90){
                                flyinggrainx[i].north=true;
                                flyinggrainy[i].north=true;
                        }
                        if(angle>90 && angle<180){
                                flyinggrainx[i].east=true;
                                flyinggrainy[i].north=true;
                        }
                        if(angle==180){
                                flyinggrainx[i].east=true;
                                flyinggrainy[i].east=true;
                        }
                        if(angle>180 && angle<270){
                                flyinggrainx[i].east=true;
                                flyinggrainy[i].south=true;
                        }
                        if(angle==270){
                                flyinggrainx[i].south=true;
                                flyinggrainy[i].south=true;
                        }
                        if(angle>270 && angle<360){
                                flyinggrainx[i].west=true;
                                flyinggrainy[i].south=true;
                        }

                        flyinggrainx[i].setOption(dic);
                        flyinggrainy[i].setOption(dic);
                }
                timer=new Timer(timeevent,"");
                timer.enabled=true;
                timer.interval=interval;

        }

        function timeevent(){
                for(var i=0;i<num;i++){
                        if(!flyinggrainx[i].appear)
                                flyinggrainx[i].appear=true if Math.random()<appearprob;
                        else{
                                flyinggrainx[i].setPosition();
                                flyinggrainx[i].setOpacity();
                        }
                       
                        if(!flyinggrainy[i].appear)
                                flyinggrainy[i].appear=true if Math.random()<appearprob;
                        else{
                                flyinggrainy[i].setPosition();
                                flyinggrainy[i].setOpacity();
                        }
                }
                if(vanishcount>=num*2){
                        timer.enabled=false;
                        stopFlying();
                }
                totaltime-=interval if totaltime!==void;
        }

        function setVanish(){
                for(var i=0;i<num;i++){
                        flyinggrainx[i].vanishing=true;
                        flyinggrainy[i].vanishing=true;
                }
        }

        function stopFlying(){
                for(var i=0;i<num;i++){
                        flyinggrainx[i].stopMove();
                        invalidate flyinggrainx[i] if flyinggrainx[i]!==void;
                        flyinggrainy[i].stopMove();
                        invalidate flyinggrainy[i] if flyinggrainy[i]!==void;
                }
                invalidate flyinggrainx if flyinggrainx!==void;
                invalidate flyinggrainy if flyinggrainy!==void;
                flyinggrainx=void;
                flyinggrainy=void;
                flyinggrainx=[];
                flyinggrainy=[];

                invalidate timer;
                timer=void;

                invalidate dic if dic!==void;
                dic=void;
                dic=%[];
        }
}
kag.addPlugin(global.skyrotateflying_object=new SkyRotateFlying(kag));

@endscript

@macro name=rflying
@eval exp="global.skyrotateflying_object.startFlying(mp)"
@endmacro

@macro name=stoprflying
@eval exp="global.skyrotateflying_object.stopFlying()"
@endmacro

@macro name=vanishrflying
@eval exp="global.skyrotateflying_object.setVanish()"
@endmacro

@macro name=leafrflying
@rflying storage=%storage|leaf num=%num angle=%angle|30.0 angleoffset=%angleoffset|20.0 speedoffset=%speedoffset|20.0 speed=%speed|5.0 accel=%accel|0.05 rspeedoffset=%rspeedoffset|12.0 rspeed=%rspeed|1.0 raccel=%raccel totaltime=%totaltime|20000 appearprob=%appearprob
@endmacro

@macro name=starrflying
@rflying storage=%storage|star num=%num angle=%angle|30.0 angleoffset=%angleoffset|20.0 speedoffset=%speedoffset|20.0 speed=%speed|5.0 accel=%accel|0.05 pspeedoffset=%pspeedoffset|60.0 pspeed=%pspeed|40.0 paccel=%paccel totaltime=%totaltime|20000 appearprob=%appearprob
@endmacro

@macro name=rjump
@rflying storage=%storage|ball num=%num angle=%angle|-90  speedoffset=%speedoffset|30.0 speed=%speed|10.0 accel=%accel|-1 rspeedoffset=%rspeedoffset|12.0 rspeed=%rspeed|1.0 paccel=%paccel totaltime=%totaltime|20000 appearprob=%appearprob
@endmacro

@return
[/code]

[[i] 本帖最后由 karryngai 于 2007-6-22 19:36 编辑 [/i]]

2007-6-18 14:18 karryngai
这个东西不好的地方是粒子数不能设计得太多,否则电脑随时会挂掉,50个粒子(25*2)大概是极限了
至于等比放大和缩小的作用,偶还想不出什么比较漂亮的粒子移动画面,大家可以发挥想象力去弄这个东西


算法上是使用copyaffine和物理上的加速度实现的,因为使用了copyaffine,所以速度会很慢,算法没有采用zoomrot或ModuleLayer里的,原因是那个东西,减速减到0后就不能再减了

2007-6-18 17:34 supervanship
这个东西大赞……
最近正在愁这个东西啊…………
学习学习!!

2007-6-19 10:20 supervanship
发现了一个小问题
就是sspeed
放大会不停的进行下去
新出來的粒子仍然接着消失的大小继续放大……直到……直到当机……
能不能让每个粒子放大然而新产生的粒子是原来的大小呢……
就是那种渐渐飘近的感觉……

还有个小问题就是粒子放大倍数太多会不好看
可是如果把粒子缩小的话问题就不大了
能不能设定那种原粒子出现时的百分比(加一个好不?)

第三问
可以定义一个新的stop么,让已有(或是等待已有的)花瓣飘完而不是突然消失
或者是改成新写一个标签时已经留在画面上运动的粒子不会突然消失不见而是继续运动到消失
我TJS完全没有开工……麻烦专员解决一下

[[i] 本帖最后由 supervanship 于 2007-6-19 12:35 编辑 [/i]]

2007-6-20 12:41 karryngai
已修正放大缩小的bug,第一个问题而解决,把sscale=0放到if语句里就解决了,话说当时偶为什么要把它放在外面。。。= =,同时也发现了一个小bug,而解决掉
关于第二个问题,能否制作一张较大的清晰图片,把开始时的比例设定得较小,这样就不会出现锯齿了
ps:惊奇地发现,偶在说明中打少了两个主要的东西,s和p,补充上去了
s是初始时的形状比例,p是初始时的透明度。。。这两个东西太重要了。。。= =,居然会打少了。。。
第三个问题,如果你设定了time的话,粒子是会飘完才消失的,如果要使用stop有这个效果的话,偶回头再想
感谢对偶的程序提出问题,偶尽快解决

[[i] 本帖最后由 karryngai 于 2007-6-20 16:29 编辑 [/i]]

2007-6-21 11:06 karryngai
已修改出来了。。。使用vanishrflying就行。。。
未太仔细debug, 麻烦debug一下

[[i] 本帖最后由 karryngai 于 2007-6-21 11:11 编辑 [/i]]

2007-6-21 12:53 supervanship
其实那个不断放大也是有用的……
上回忘记说要保留了……
又要麻烦修改啊

2007-6-22 19:39 karryngai
已修改出来了...用keepsaccel就能让形状不断变化,用keepaccel就能让速度不断加速...建议不要用后者...这个东西貌似变得很恐怖了...参数这么多....

2007-6-22 22:28 咔莎
我已经变成米粒了……拿来主义者。。

页: [1]


Powered by Discuz! Archiver 5.5.0  © 2001-2006 Comsenz Inc.