您当前的位置: 首页 >  ar

Jave.Lin

暂无认证

  • 4浏览

    0关注

    704博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

AS3 Starling extends Particle System 分析

Jave.Lin 发布时间:2013-03-21 14:55:07 ,浏览量:4

Starling extentions Particle System Author : Gamua OG 分析作者:Jave.lin 原文: http://blog.csdn.net/linjf520/article/details/8701354 这是Starling扩展的粒子系统 下来源码,与DEMO运行后,发现效果很强大,于是开始研究其结构; 1、粒子的初始化: 初始化主要处理以下内容:决定粒子的初始值、与大部分的过渡值;部份过渡值只能在过渡时的公式下决定 在粒子的初始化时,可以考虑使用以下方式来初始化: 思路:每个值,都由:本来的值+波动值 2、粒子的过渡更新 主要是应用初始化决定的:目标值 与 终止值,而使用过渡值的一个更新过渡 function ranWave(value):Number{//波动函数  return Math.random()*(value*2)-value; } function rw(v):Number{return ranWave(v);} 生命周期 a 10 生命周期波动值 b 5 则生命周期在生成时 c 10+5*(-1~1) c=a+rw(b) e.g. class ColorArgb {  alpha:Number; //透明通道值:0~1  red:Number; //红色通道值:0~1  green:Number; //绿色通道值:0~1  blue:Number; //蓝色通道值:0~1  function toArgb():int;  function fromArgb(v:int):void;  function toRbg():int;  function fromRgb(v:int):void; } class Particle //粒子基础数据定义--用于直接呈现的数据 {  x:Number; //粒子x坐标位置  y:Number; //粒子y坐标位置  scale:Number; //缩放  rotation:Number; //当前的弧度,可以理解为:自转,角度,实在不明白就:百度:自转,这里不加说明;  color:uint; //当前的着色值  currentTime:int; //当前已消耗的生命周期数值记录  totalTime:int; //总的生命周期 } class PDParticle //Proccess Distance ( or Delta ) values Particle 用于动画数据过度时处理的数据 extends Particle {  //放射型发射器用到的变量  colorArgb:ColorArgb; //当前着色四个值的管理  colorArgbDelta:ColorArgb; //当前的着色值的四通道值的过渡值(每帧处理的比率值)  var startX:Number, startY:Number;//记录发射器的X,Y位置,当粒子与发射点距离,作旋转、重力、的控制  var velocityX:Number, velocityY:Number;//当前X,Y上的轴速度  //径向型发射器用到的变量  var emitRadius:Number; //发射的半径(即,与startX,startY的相对距离值)  var emitRadiusDelta:Number; //半径过程变量值  var emitRotation:Number; //发射角度,相对startX,startY的角度,可以理解为:公转,角度,实在不明白就:百度:公转,这里不加说明;  var emitRotationDelta:Number; //发射角度过程变量值  var rotationDelta:Number; //粒子自身的对度发射点的角度变化过渡值  var radialAcceleration:Number; //当前放射速度  var tangentialAcceleration:Number;//这个在应用时的算法上比较难懂,但只要在纸上画一下,就是把速度向量方向-Math.PI的效果,这样就会有:螺旋效果了  var scaleDelta:Number; //缩放过渡变化值 } class ParticleEmitter extends DisplayObject implements IAnimatable //应用数据(即时数据),呈现发射器 {  //单位粒子的纹理配置(供外部工具调整,而导出的配置之一的数据)  var texture:Texture;  function void advanceTime(passedTime:Number):void;  function void advancePs(ps:Particle, passedTime:Number):void;  function void start(duration:Number=Number.MAX_VALUE):void;  function void stop(clearPs:Boolean=falsel):void; } class PDParticleEmitter extends ParticleEmitter //数据过渡处理发射器 {  static const EMITTER_TYPE_GRAVITY:int = 0; //内聚型发射器(这里的Gravity译为:引力、吸引力,即为:内聚引力)  static const EMITTER_TYPE_RADIAL:int = 1; //与内聚反向:发散型发射器  //每帧的处理时间  var frameTime:Number; //在单帧的update时,处理粒子的循环发射时使用的时间  //发射器配置(供外部工具调整,而导出的配置之一的数据)  var emitterType:int; //发射器类型:目前只有两种:发散型、内聚型  var emitterX:Number,emitterY:Number; //发射器x,y,决定,单个粒子的起始位置的变量之一  var emitterXVariance:Number,emitterYVariance:Number;//发射器x,y的位置波动值  var emitterDuration:Number; //发射器的持续时间(相当于:发射器的生命周期),默认以:Number.MAX_VALUE时,说明是无限循环的方式  var emitterRate:Number; //该可以理解为:创建单个粒子的时间,在初始化时,根据:maxNumPs/lifespan(最大粒子数/单个粒子生命周期),来定值  //粒子配置(供外部工具调整,而导出的配置之一的数据)  var maxNumPs:int; //最大粒子数  var lifespan:Number; //单个粒子生命周期  var lifespanVariance; //在初始化时,加到:单个粒子生命周期的波动值  var angle:Number; //发射粒子的角度(单位:弧度)  var angleVariance:Number; //角度的波动值  var startSize:Number; //初始大小值(注意,这里不是缩放值,而是width,height之类的大小(size)值,而不是缩放(scale),但最终运行时,会与大小相除转成对应的缩放值)  var startSizeVariance:Number; //初始大小波动值  var endSize:Number; //终止(目标)大小值  var endSizeVariance:Number; //终止大小波动值  var startRotation:Number; //初始角度(弧度)  var startRotationVariance:Number; //初始角度波动值  var endRotation:Number; //终止角度  var endRotationVariance:Number; //终止角度波动值  //重力、运动速度配置(供外部工具调整,而导出的配置之一的数据)  var speed:Number; //粒子的速度值  var speedVariance:Number; //速度波动值  var radialAcceleration:Number; //放射型的放射速度(单个粒子的自身:startX,startY:发射器位置,与当前位置:x,y的距离连线,形成的向量(放射向量))上的加速度  var radialAccelerationVariance:Number; //放射速度波动值   var tangentialAcceleration:Number; //正切--tan的加成速度(螺旋速度值)  var tangentialAccelerationVariance:Number;//螺旋波动值  var gravityX:Number; //重力向量X值  var gravityY:Number; //重力向量Y值  //放射型粒子配置(供外部工具调整,而导出的配置之一的数据)  var maxRadius:Number; //最大的发射半径  var maxRadiusVariance:Number; //最大半径波动值  var minRadius:Number; //最小的发射半径  var rotatePerSecond:Number; //每秒的旋转弧度  var rotatePerSecondVariance:Number; //旋转弧度的波动值  //颜色配置(供外部工具调整,而导出的配置之一的数据)  var startColor:ColorArgb; //初始颜色  var startColorVariance:ColorArgb; //初始颜色波动值  var endColor:ColorArgb; //终止(目标)颜色  var endColorVariance:ColorArgb; //终止颜色波动值  //初始化函数  function initializePs(ps:PDParticle):void  {   var ls:Number = lifespan + rw(lifespanVariance);//生命周期   if(ls == 0) reutrn; //生命周期为0的,可以忽略不处理      ps.currentTime = 0; //重置当前粒子已消耗的生命时间   ps.totoalTime = ls; //设置粒子的最大生命周期   ps.x = emitterX + rw(emitterXVariance);//设置当前位置   ps.y = emitterY + rw(emitterYVariance);   ps.startX = emitterX; //记录射点起来位置   ps.startY = emitterY;      var a:Number = emitterAngle + rw(angleVariance);   var s:Number = emitterSpeed + rw(speedVariance);   ps.velocityX = s * Math.cos(a); //x,y轴上的轴速度;(可以封装2D向量处理也可以,不过粒子的封装最好不要过多层次,能以最小的封装来处理,性能上会好一些)   ps.velocityY = s * Math.sin(a);   ps.emitRadius = maxRadius + rw(maxRadiusVariance);   ps.emitRadiusDelta = maxRadius / ls; //与该粒子的生命期周时间作一个等分为比率过渡值   ps.emitRotation = angle + rw(angleVariance);//在径向型的发射器处理时,与分散型的发射角度一样   ps.emitRotationDelta = rotatePerSecond + rw(rotatePerSecondVariance);//发射器角度过渡变化值   ps.radialAcceleration = radialAcceleration + rw(radialAccelerationVariance);//放射加速度,放射速度如果为很大的负数-Max,那就是像个黑洞一样;将所有粒子向内发射,然后爆炸的效果,我设置为-3800的时候就比较像黑洞内聚力效果   ps.tangentialAcceleration = tangentialAccelertaion + rw(tangentialAccelerationVariance);   var ss:Number = startSize + rw(startSizeVariance);   var es:Number = endSize + rw(endSizeVariance);   if(ss < .1) ss = .1;   if(es < .1) es = .1;   ps.scale = ss / texture.width;   ps.scaleDelta = ((es - ss) / ls) / texture.width;//用终止值-始化值=距离值,再用这个距离值,除:该粒子的生命周期,即:得到:变化率,再用变化率(尺寸值比率) * 原纹理尺寸值大小,最终得到该值:缩放过渡变化值,这里为啥只乘宽度,因为我们先这里只处理,等比例缩放,不做不等比例;   // colors                var sc:ColorArgb = ps.colorArgb; //用于决定初始化颜色   var colorDelta:ColorArgb = ps.colorArgbDelta; //用于决定过渡处理时的颜色,四通道,各种的变化率                sc.red   = startColor.red;   sc.green = startColor.green;   sc.blue  = startColor.blue;   sc.alpha = startColor.alpha;   if (startColorVariance.red != 0)   sc.red   += rw(startColorVariance.red); //如果初始颜色,各通道有值才处理波动累加;   if (startColorVariance.green != 0) sc.green += rw(startColorVariance.green);   if (startColorVariance.blue != 0)  sc.blue  += rw(startColorVariance.blue);   if (startColorVariance.alpha != 0) sc.alpha += rw(startColorVariance.alpha);   var ecRed:Number   = endColor.red;   var ecGreen:Number = endColor.green;   var ecBlue:Number  = endColor.blue;   var ecAlpha:Number = endColor.alpha;   if (endColorVariance.red != 0)   ecRed   += rw(endColorVariance.red); //终止初始颜色,各通道有值才处理波动累加;   if (endColorVariance.green != 0) ecGreen += rw(endColorVariance.green);   if (endColorVariance.blue != 0)  ecBlue  += rw(endColorVariance.blue);   if (endColorVariance.alpha != 0) ecAlpha += rw(endColorVariance.alpha);   colorDelta.red   = (ecRed   - sc.red)   / ls; //以(目标值-初始值)/总消时(生命周期)=每次单位(这里可以是:秒,或是毫秒,这里可以自由转,或是其它单位)更新过渡变化率值,外国人都喜欢把这些变化值叫:delta   colorDelta.green = (ecGreen - sc.green) / ls;   colorDelta.blue  = (ecBlue  - sc.blue)  / ls;   colorDelta.alpha = (ecAlpha - sc.alpha) / ls;   // rotation   var sr:Number = startRotation + rw(startRotationVariance);   var er:Number   = endRotation   + rw(endRotationVariance);   ps.rotation = sr; //决定初始角度、终止角度   ps.rotationDelta = (er - sr) / ls;  }  //更新 “初始值” 到 “终止值” 的函数  override function advancePs(ps:Particle,passedTime:Number):void  {   //过渡变化处理,以下我都简称为:pd'   var pdps:PDParticle = ps as PDParticle;      var restTime:Number = pdps.totalTime - pdps.currentTime;   passedTime = restTime > passedTime ? passedTime : restTime;//因为以会passedTime来做一些过渡因数,所以这里调整为,还剩最后一次更新的粒子的时间因数作调整   pdps.currentTime += passedTime;   if(emitterType == EMITTER_TYPE_GRAVITY)   {//内聚型    pdps.emitRotation += pdps.emitRotationDelta * passTime; //pd'粒子对应emitterX,Y的角度;    pdps.emitRadius -= pdps.emitRadiusDelta * passTime; //pd'粒子距离emitterX,Y半径    pdps.x = emitterX - Math.cos(pdps.emitRotation) * pdps.emitRadius;    pdps.y = emitterY - Math.sin(pdps.emitRotation) * pdps.emitRadius;        if(pdps.emitRadius < minRadius) //当半径值比最小值还小时,就相当于,该粒子已‘挂’(生命周期为止)     pdps.currentTime = pdps.totalTime;   }   else   {//发散型    var disX:Number = pdps.x - pdps.startX;//前面我说了,startX只是拿来作该粒子初始化时,记录emtterX的位置;这里使用当前位置-记录发射器位置,就是求该粒子当次生命周期中的,已发散距离    var disY:Number = pdps.y - pdps.startY;//同上    var disScale:Number = Math.sqrt(disX*disX + disY*disY); //这里的运算原理,我也不知道;同求解;同公式中可以知道,disX,disY与disScale是成倍的正比    if(disScale < .01) disScale = .01; //作者这里调整最小于不低于:.01的意思:1、以下应用有作为除数;2、即时粒子已发散距离很小,但至少还得很微量的动画调整因数作用        var rX:Number = disX / disScale;    var rY:Number = disY / disScale;    var tanX:Number = rX; //这里我前面讲到过,就是作:螺旋转速度的因数;    var tanY:Number = rY;        rX *= pdps.radialAcceleration; //粒子的发散加速应用    rY *= pdps.radialAcceleration;    var dumpTanX:Number = tanX; //备份一下tanX,这里开始就是我上面所说的,螺旋运算,转-90度的方向调整    tanX = -tanY * pdps.tangentialAcceleration;    tanY = dumTanX * pdps.tangentialAcceleration;    pdps.velocityX += passedTime * (gravityX + radialX + tanX); //注意这里的passedTime作用,前面我说到,passedTime的调整,最后一次为最后生命时间,这样效果才是比较合理的    pdps.velocityY += passedTime * (gravityY + radialY + tanY); //所有:重力、发散、螺旋 ,等等,这些速度,都与passedTime有关,如果当前这帧的时间很小(说明FPS很高),那么过渡动画数据就会呈现越细    pdps.x += pdps.velocityX * passedTime; //pd'重力、发散、螺旋    pdps.y += pdps.velocityY * passedTime;   }   pdps.scale += pdps.scaleDelta * passedTime; //pd'缩放   pdps.rotation += pdps.rotaionDelta * passedTime; //pd'自转角度   pdps.colorArgb.red += pdps.colorArgbDelta.red * passedTime; //pd'颜色   pdps.colorArgb.green += pdps.colorArgbDelta.green * passedTime;   pdps.colorArgb.blue += pdps.colorArgbDelta.blue * passedTime;   pdps.colorArgb.alpha += pdps.colorArgbDelta.alpha * passedTime;   pdps.color = pdps.colorArgb.toRgb(); //最终应用颜色值RGB   pdps.alpha = pdps.colorArgb.alpha;  } } 好了,就分析到这里;
关注
打赏
1664331872
查看更多评论
立即登录/注册

微信扫码登录

0.0493s