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;
}
}
好了,就分析到这里;
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;
}
}
好了,就分析到这里;