You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
665 lines
24 KiB
665 lines
24 KiB
|
|
//const { ccclass, property } = cc._decorator;
|
|
|
|
/**
|
|
* 单个粒子信息
|
|
*/
|
|
export class MyParticle {
|
|
pos = cc.v2(0, 0);
|
|
startPos = cc.v2(0, 0);
|
|
color = cc.color(0, 0, 0, 255);
|
|
deltaColor = { r: 0, g: 0, b: 0, a: 255 };
|
|
size = 0;
|
|
deltaSize = 0;
|
|
rotation = 0;
|
|
deltaRotation = 0;
|
|
timeToLive = 0;
|
|
drawPos = cc.v2(0, 0);
|
|
aspectRatio = 1;
|
|
// Mode A
|
|
dir = cc.v2(0, 0);
|
|
radialAccel = 0;
|
|
tangentialAccel = 0;
|
|
// Mode B
|
|
angle = 0;
|
|
degreesPerSecond = 0;
|
|
radius = 0;
|
|
deltaRadius = 0;
|
|
|
|
frameindex = 0//当前帧
|
|
lastFrameTime = 0;
|
|
topLife = 0; //当刷新帧率为-1时,自动按总生活周期
|
|
|
|
init() {
|
|
this.pos.set(cc.Vec2.ZERO)
|
|
this.startPos.set(cc.Vec2.ZERO)
|
|
this.color.fromHEX('0xFF000000');
|
|
|
|
this.deltaColor.r = this.deltaColor.g = this.deltaColor.b = 0;
|
|
this.deltaColor.a = 255;
|
|
this.size = 0;
|
|
this.deltaSize = 0;
|
|
this.rotation = 0;
|
|
this.deltaRotation = 0;
|
|
this.timeToLive = 0;
|
|
this.drawPos.set(cc.Vec2.ZERO)
|
|
this.aspectRatio = 1;
|
|
// Mode A
|
|
this.dir.set(cc.Vec2.ZERO)
|
|
this.radialAccel = 0;
|
|
this.tangentialAccel = 0;
|
|
// Mode B
|
|
this.angle = 0;
|
|
this.degreesPerSecond = 0;
|
|
this.radius = 0;
|
|
this.deltaRadius = 0;
|
|
|
|
this.frameindex = 0//当前帧
|
|
this.lastFrameTime = 0;
|
|
this.topLife = 0; //当刷新帧率为-1时,自动按总生活周期
|
|
}
|
|
}
|
|
|
|
export default class MyParticleSimulator {
|
|
pool: cc.js.Pool;
|
|
// sys: MyParticleSysInfo;
|
|
sys: cc.ParticleSystem;
|
|
particles: MyParticle[] = null;
|
|
active: boolean = false;
|
|
readyToPlay: boolean = true;
|
|
finished: boolean = false;
|
|
elapsed: number = 0;
|
|
emitCounter: number = 0;
|
|
_uvFilled: number = 0;
|
|
_worldRotation: number = 0;
|
|
animationRate: number = 0; //帧率
|
|
animFrameNums: number = 0; //图片有几帧
|
|
_pos = new cc.Vec2(0, 0);
|
|
_tpa = new cc.Vec2(0, 0);
|
|
_tpb = new cc.Vec2(0, 0);
|
|
_tpc = new cc.Vec2(0, 0);
|
|
|
|
constructor(system, frameNums, animRate) {
|
|
this.pool = new cc.js.Pool((par: MyParticle) => {
|
|
par.pos.set(cc.Vec2.ZERO)
|
|
par.startPos.set(cc.Vec2.ZERO)
|
|
par.color.fromHEX('0xFF000000');
|
|
|
|
par.deltaColor.r = par.deltaColor.g = par.deltaColor.b = 0;
|
|
par.deltaColor.a = 255;
|
|
par.size = 0;
|
|
par.deltaSize = 0;
|
|
par.rotation = 0;
|
|
par.deltaRotation = 0;
|
|
par.timeToLive = 0;
|
|
par.drawPos.set(cc.Vec2.ZERO)
|
|
par.aspectRatio = 1;
|
|
// Mode A
|
|
par.dir.set(cc.Vec2.ZERO)
|
|
par.radialAccel = 0;
|
|
par.tangentialAccel = 0;
|
|
// Mode B
|
|
par.angle = 0;
|
|
par.degreesPerSecond = 0;
|
|
par.radius = 0;
|
|
par.deltaRadius = 0;
|
|
|
|
par.frameindex = 0//当前帧
|
|
par.lastFrameTime = 0;
|
|
par.topLife = 0; //当刷新帧率为-1时,自动按总生活周期
|
|
}, 1024);
|
|
|
|
this.sys = system;
|
|
this.particles = [];
|
|
this.active = false;
|
|
this.readyToPlay = true;
|
|
this.finished = false;
|
|
this.elapsed = 0;
|
|
this.emitCounter = 0;
|
|
this._uvFilled = 0;
|
|
this._worldRotation = 0;
|
|
this.animationRate = animRate;
|
|
this.animFrameNums = frameNums;
|
|
|
|
this.pool.get = function () {
|
|
return this._get() || new MyParticle();
|
|
};
|
|
}
|
|
|
|
stop() {
|
|
this.active = false;
|
|
this.readyToPlay = false;
|
|
this.elapsed = this.sys.duration;
|
|
this.emitCounter = 0;
|
|
}
|
|
|
|
reset() {
|
|
cc.js.Pool
|
|
this.active = true;
|
|
this.readyToPlay = true;
|
|
this.elapsed = 0;
|
|
this.emitCounter = 0;
|
|
this.finished = false;
|
|
let particles = this.particles;
|
|
for (let id = 0; id < particles.length; ++id) {
|
|
this.pool.put(particles[id]);
|
|
}
|
|
particles.length = 0;
|
|
}
|
|
|
|
/**
|
|
* 开始喷射
|
|
*/
|
|
emitParticle(pos) {
|
|
let psys = this.sys;
|
|
let clampf = cc.misc.clampf;
|
|
let particle = this.pool.get();
|
|
this.particles.push(particle);
|
|
particle.timeToLive = psys.life + psys.lifeVar * (Math.random() - 0.5) * 2;
|
|
// Init particle
|
|
// timeToLive
|
|
// no negative life. prevent division by 0
|
|
particle.timeToLive = psys.life + psys.lifeVar * (Math.random() - 0.5) * 2;
|
|
let timeToLive = particle.timeToLive = Math.max(0, particle.timeToLive);
|
|
|
|
// position
|
|
particle.pos.x = psys.sourcePos.x + psys.posVar.x * (Math.random() - 0.5) * 2;
|
|
particle.pos.y = psys.sourcePos.y + psys.posVar.y * (Math.random() - 0.5) * 2;
|
|
|
|
// Color
|
|
let sr, sg, sb, sa;
|
|
let startColor = psys.startColor, startColorVar = psys.startColorVar;
|
|
let endColor = psys.endColor, endColorVar = psys.endColorVar;
|
|
particle.color.r = sr = clampf(startColor.r + startColorVar.r * (Math.random() - 0.5) * 2, 0, 255);
|
|
particle.color.g = sg = clampf(startColor.g + startColorVar.g * (Math.random() - 0.5) * 2, 0, 255);
|
|
particle.color.b = sb = clampf(startColor.b + startColorVar.b * (Math.random() - 0.5) * 2, 0, 255);
|
|
particle.color.a = sa = clampf(startColor.a + startColorVar.a * (Math.random() - 0.5) * 2, 0, 255);
|
|
particle.deltaColor.r = (clampf(endColor.r + endColorVar.r * (Math.random() - 0.5) * 2, 0, 255) - sr) / timeToLive;
|
|
particle.deltaColor.g = (clampf(endColor.g + endColorVar.g * (Math.random() - 0.5) * 2, 0, 255) - sg) / timeToLive;
|
|
particle.deltaColor.b = (clampf(endColor.b + endColorVar.b * (Math.random() - 0.5) * 2, 0, 255) - sb) / timeToLive;
|
|
particle.deltaColor.a = (clampf(endColor.a + endColorVar.a * (Math.random() - 0.5) * 2, 0, 255) - sa) / timeToLive;
|
|
|
|
// size
|
|
let startS = psys.startSize + psys.startSizeVar * (Math.random() - 0.5) * 2;
|
|
startS = Math.max(0, startS); // No negative value
|
|
particle.size = startS;
|
|
if (psys.endSize === cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE) {
|
|
particle.deltaSize = 0;
|
|
} else {
|
|
var endS = psys.endSize + psys.endSizeVar * (Math.random() - 0.5) * 2;
|
|
endS = Math.max(0, endS); // No negative values
|
|
particle.deltaSize = (endS - startS) / timeToLive;
|
|
}
|
|
|
|
// rotation
|
|
var startA = psys.startSpin + psys.startSpinVar * (Math.random() - 0.5) * 2;
|
|
var endA = psys.endSpin + psys.endSpinVar * (Math.random() - 0.5) * 2;
|
|
particle.rotation = startA;
|
|
particle.deltaRotation = (endA - startA) / timeToLive;
|
|
|
|
// position
|
|
particle.startPos.x = pos.x;
|
|
particle.startPos.y = pos.y;
|
|
|
|
// aspect ratio
|
|
particle.aspectRatio = this.sys['_aspectRatio'] || 1;
|
|
|
|
// direction
|
|
let a = cc.misc.degreesToRadians(psys.angle + this._worldRotation + psys.angleVar * (Math.random() - 0.5) * 2);
|
|
// Mode Gravity: A
|
|
if (psys.emitterMode === cc.ParticleSystem.EmitterMode.GRAVITY) {
|
|
let s = psys.speed + psys.speedVar * (Math.random() - 0.5) * 2;
|
|
// direction
|
|
particle.dir.x = Math.cos(a);
|
|
particle.dir.y = Math.sin(a);
|
|
particle.dir.mulSelf(s);
|
|
// radial accel
|
|
particle.radialAccel = psys.radialAccel + psys.radialAccelVar * (Math.random() - 0.5) * 2;
|
|
// tangential accel
|
|
particle.tangentialAccel = psys.tangentialAccel + psys.tangentialAccelVar * (Math.random() - 0.5) * 2;
|
|
// rotation is dir
|
|
if (psys.rotationIsDir) {
|
|
particle.rotation = -cc.misc.radiansToDegrees(Math.atan2(particle.dir.y, particle.dir.x));
|
|
}
|
|
}
|
|
// Mode Radius: B
|
|
else {
|
|
// Set the default diameter of the particle from the source position
|
|
var startRadius = psys.startRadius + psys.startRadiusVar * (Math.random() - 0.5) * 2;
|
|
var endRadius = psys.endRadius + psys.endRadiusVar * (Math.random() - 0.5) * 2;
|
|
particle.radius = startRadius;
|
|
particle.deltaRadius = (psys.endRadius === cc.ParticleSystem.START_RADIUS_EQUAL_TO_END_RADIUS) ? 0 : (endRadius - startRadius) / timeToLive;
|
|
particle.angle = a;
|
|
particle.degreesPerSecond = cc.misc.degreesToRadians(psys.rotatePerS + psys.rotatePerSVar * (Math.random() - 0.5) * 2);
|
|
}
|
|
|
|
|
|
particle.frameindex = 0;
|
|
particle.lastFrameTime = particle.timeToLive;
|
|
particle.topLife = particle.timeToLive;
|
|
}
|
|
|
|
getWorldRotation(node) {
|
|
let rotation = 0;
|
|
let tempNode = node;
|
|
while (tempNode) {
|
|
rotation += tempNode.angle;
|
|
tempNode = tempNode.parent;
|
|
}
|
|
return rotation;
|
|
}
|
|
|
|
|
|
updateUVs(force) {
|
|
let assembler = this.sys['_assembler'];
|
|
if (!assembler) {
|
|
return;
|
|
}
|
|
let buffer = this.sys['_assembler'].getBuffer();
|
|
if (buffer) {
|
|
const FLOAT_PER_PARTICLE = 4 * this.sys['_assembler']._vfmt._bytes / 4;
|
|
let vbuf = buffer._vData;
|
|
let uv = this.sys['_renderSpriteFrame'].uv;
|
|
|
|
let start = force ? 0 : this._uvFilled;
|
|
let particleCount = this.particles.length;
|
|
for (let i = start; i < particleCount; i++) {
|
|
let offset = i * FLOAT_PER_PARTICLE;
|
|
vbuf[offset + 2] = uv[0];
|
|
vbuf[offset + 3] = uv[1];
|
|
vbuf[offset + 7] = uv[2];
|
|
vbuf[offset + 8] = uv[3];
|
|
vbuf[offset + 12] = uv[4];
|
|
vbuf[offset + 13] = uv[5];
|
|
vbuf[offset + 17] = uv[6];
|
|
vbuf[offset + 18] = uv[7];
|
|
}
|
|
this._uvFilled = particleCount;
|
|
}
|
|
}
|
|
|
|
updateParticleBuffer(particle, pos, buffer, offset) {
|
|
let vbuf = buffer._vData;
|
|
let uintbuf = buffer._uintVData;
|
|
|
|
let x = pos.x, y = pos.y;
|
|
let width = particle.size;
|
|
let height = width;
|
|
let aspectRatio = particle.aspectRatio;
|
|
aspectRatio > 1 ? (height = width / aspectRatio) : (width = height * aspectRatio);
|
|
width = width / this.animFrameNums;
|
|
let halfWidth = width / 2;
|
|
let halfHeight = height / 2;
|
|
// pos
|
|
if (particle.rotation) {
|
|
let x1 = -halfWidth, y1 = -halfHeight;
|
|
let x2 = halfWidth, y2 = halfHeight;
|
|
let rad = -cc.misc.degreesToRadians(particle.rotation);
|
|
let cr = Math.cos(rad), sr = Math.sin(rad);
|
|
// bl
|
|
vbuf[offset] = x1 * cr - y1 * sr + x;
|
|
vbuf[offset + 1] = x1 * sr + y1 * cr + y;
|
|
// br
|
|
vbuf[offset + 5] = x2 * cr - y1 * sr + x;
|
|
vbuf[offset + 6] = x2 * sr + y1 * cr + y;
|
|
// tl
|
|
vbuf[offset + 10] = x1 * cr - y2 * sr + x;
|
|
vbuf[offset + 11] = x1 * sr + y2 * cr + y;
|
|
// tr
|
|
vbuf[offset + 15] = x2 * cr - y2 * sr + x;
|
|
vbuf[offset + 16] = x2 * sr + y2 * cr + y;
|
|
}
|
|
else {
|
|
// bl
|
|
vbuf[offset] = x - halfWidth;
|
|
vbuf[offset + 1] = y - halfHeight;
|
|
// br
|
|
vbuf[offset + 5] = x + halfWidth;
|
|
vbuf[offset + 6] = y - halfHeight;
|
|
// tl
|
|
vbuf[offset + 10] = x - halfWidth;
|
|
vbuf[offset + 11] = y + halfHeight;
|
|
// tr
|
|
vbuf[offset + 15] = x + halfWidth;
|
|
vbuf[offset + 16] = y + halfHeight;
|
|
}
|
|
|
|
|
|
if (this.animFrameNums > 1) {
|
|
if (this.animationRate == -1) {
|
|
//自动的
|
|
var fix = 1 / this.animFrameNums;
|
|
let fixTimes = particle.topLife / this.animFrameNums;
|
|
let idx = Math.floor(particle.timeToLive / fixTimes);
|
|
idx = this.animFrameNums - idx - 1;
|
|
vbuf[offset + 2] = fix * idx;
|
|
vbuf[offset + 12] = fix * idx;
|
|
vbuf[offset + 7] = vbuf[offset + 2] + fix;
|
|
vbuf[offset + 17] = vbuf[offset + 7];
|
|
} else {
|
|
let duration = 1 / this.animationRate;
|
|
var fix = 1 / this.animFrameNums;
|
|
|
|
|
|
vbuf[offset + 2] = fix * particle.frameindex;
|
|
vbuf[offset + 12] = fix * particle.frameindex;
|
|
vbuf[offset + 7] = vbuf[offset + 2] + fix;
|
|
vbuf[offset + 17] = vbuf[offset + 7];
|
|
|
|
if (particle.lastFrameTime - particle.timeToLive > duration) {
|
|
particle.frameindex += 1;
|
|
particle.lastFrameTime = particle.timeToLive;
|
|
if (particle.frameindex >= this.animFrameNums) {
|
|
particle.frameindex = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// color
|
|
uintbuf[offset + 4] = particle.color._val;
|
|
uintbuf[offset + 9] = particle.color._val;
|
|
uintbuf[offset + 14] = particle.color._val;
|
|
uintbuf[offset + 19] = particle.color._val;
|
|
}
|
|
|
|
step(dt) {
|
|
dt = dt > cc.director['_maxParticleDeltaTime'] ? cc.director['_maxParticleDeltaTime'] : dt;
|
|
let psys = this.sys;
|
|
let node = psys.node;
|
|
let particles = this.particles;
|
|
const FLOAT_PER_PARTICLE = 4 * this.sys['_assembler']._vfmt._bytes / 4;
|
|
const PositionType = cc.ParticleSystem.PositionType;
|
|
|
|
// Calculate pos
|
|
node['_updateWorldMatrix']();
|
|
if (psys.positionType === PositionType.FREE) {
|
|
this._worldRotation = this.getWorldRotation(node);
|
|
let m = node['_worldMatrix'].m;
|
|
this._pos.x = m[12];
|
|
this._pos.y = m[13];
|
|
} else if (psys.positionType === PositionType.RELATIVE) {
|
|
this._worldRotation = node.angle;
|
|
this._pos.x = node.x;
|
|
this._pos.y = node.y;
|
|
} else {
|
|
this._worldRotation = 0;
|
|
}
|
|
|
|
// Emission
|
|
if (this.active && psys.emissionRate) {
|
|
var rate = 1.0 / psys.emissionRate;
|
|
//issue #1201, prevent bursts of particles, due to too high emitCounter
|
|
if (particles.length < psys.totalParticles)
|
|
this.emitCounter += dt;
|
|
|
|
while ((particles.length < psys.totalParticles) && (this.emitCounter > rate)) {
|
|
this.emitParticle(this._pos);
|
|
this.emitCounter -= rate;
|
|
}
|
|
|
|
this.elapsed += dt;
|
|
if (psys.duration !== -1 && psys.duration < this.elapsed) {
|
|
psys.stopSystem();
|
|
}
|
|
}
|
|
|
|
// Request buffer for particles
|
|
let buffer = psys['_assembler'].getBuffer();
|
|
let particleCount = particles.length;
|
|
buffer.reset();
|
|
buffer.request(particleCount * 4, particleCount * 6);
|
|
|
|
// Fill up uvs
|
|
if (particleCount > this._uvFilled) {
|
|
this.updateUVs(false);
|
|
}
|
|
|
|
// Used to reduce memory allocation / creation within the loop
|
|
let particleIdx = 0;
|
|
while (particleIdx < particles.length) {
|
|
// Reset temporary vectors
|
|
this._tpa.x = this._tpa.y = this._tpb.x = this._tpb.y = this._tpc.x = this._tpc.y = 0;
|
|
|
|
let particle = particles[particleIdx];
|
|
|
|
// life
|
|
particle.timeToLive -= dt;
|
|
if (particle.timeToLive > 0) {
|
|
// Mode A: gravity, direction, tangential accel & radial accel
|
|
if (psys.emitterMode === cc.ParticleSystem.EmitterMode.GRAVITY) {
|
|
let tmp = this._tpc, radial = this._tpa, tangential = this._tpb;
|
|
|
|
// radial acceleration
|
|
if (particle.pos.x || particle.pos.y) {
|
|
radial.set(particle.pos);
|
|
radial.normalizeSelf();
|
|
}
|
|
tangential.set(radial);
|
|
radial.mulSelf(particle.radialAccel);
|
|
|
|
// tangential acceleration
|
|
let newy = tangential.x;
|
|
tangential.x = -tangential.y;
|
|
tangential.y = newy;
|
|
|
|
tangential.mulSelf(particle.tangentialAccel);
|
|
|
|
tmp.set(radial);
|
|
tmp.addSelf(tangential);
|
|
tmp.addSelf(psys.gravity);
|
|
tmp.mulSelf(dt);
|
|
particle.dir.addSelf(tmp);
|
|
|
|
tmp.set(particle.dir);
|
|
tmp.mulSelf(dt);
|
|
particle.pos.addSelf(tmp);
|
|
}
|
|
// Mode B: radius movement
|
|
else {
|
|
// Update the angle and radius of the particle.
|
|
particle.angle += particle.degreesPerSecond * dt;
|
|
particle.radius += particle.deltaRadius * dt;
|
|
|
|
particle.pos.x = -Math.cos(particle.angle) * particle.radius;
|
|
particle.pos.y = -Math.sin(particle.angle) * particle.radius;
|
|
}
|
|
|
|
// color
|
|
particle.color.r += particle.deltaColor.r * dt;
|
|
particle.color.g += particle.deltaColor.g * dt;
|
|
particle.color.b += particle.deltaColor.b * dt;
|
|
particle.color.a += particle.deltaColor.a * dt;
|
|
|
|
// size
|
|
particle.size += particle.deltaSize * dt;
|
|
if (particle.size < 0) {
|
|
particle.size = 0;
|
|
}
|
|
|
|
// angle
|
|
particle.rotation += particle.deltaRotation * dt;
|
|
|
|
// update values in quad buffer
|
|
let newPos = this._tpa;
|
|
newPos.set(particle.pos);
|
|
if (psys.positionType !== PositionType.GROUPED) {
|
|
newPos.addSelf(particle.startPos);
|
|
}
|
|
|
|
let offset = FLOAT_PER_PARTICLE * particleIdx;
|
|
this.updateParticleBuffer(particle, newPos, buffer, offset);
|
|
|
|
// update particle counter
|
|
++particleIdx;
|
|
} else {
|
|
// life < 0
|
|
let deadParticle = particles[particleIdx];
|
|
if (particleIdx !== particles.length - 1) {
|
|
particles[particleIdx] = particles[particles.length - 1];
|
|
}
|
|
this.pool.put(deadParticle);
|
|
particles.length--;
|
|
}
|
|
}
|
|
|
|
if (particles.length > 0) {
|
|
buffer.uploadData();
|
|
psys['_assembler']._ia._count = particles.length * 6;
|
|
}
|
|
else if (!this.active && !this.readyToPlay) {
|
|
this.finished = true;
|
|
psys['_finishedSimulation']();
|
|
}
|
|
}
|
|
|
|
// Simulator.prototype.step = function (dt) {
|
|
// dt = dt > cc.director._maxParticleDeltaTime ? cc.director._maxParticleDeltaTime : dt;
|
|
// let psys = this.sys;
|
|
// let node = psys.node;
|
|
// let particles = this.particles;
|
|
// const FLOAT_PER_PARTICLE = 4 * this.sys._assembler._vfmt._bytes / 4;
|
|
// const PositionType = cc.ParticleSystem.PositionType;
|
|
|
|
// // Calculate pos
|
|
// node._updateWorldMatrix();
|
|
// if (psys.positionType === PositionType.FREE) {
|
|
// this._worldRotation = getWorldRotation(node);
|
|
// let m = node._worldMatrix.m;
|
|
// _pos.x = m[12];
|
|
// _pos.y = m[13];
|
|
// } else if (psys.positionType === PositionType.RELATIVE) {
|
|
// this._worldRotation = node.angle;
|
|
// _pos.x = node.x;
|
|
// _pos.y = node.y;
|
|
// } else {
|
|
// this._worldRotation = 0;
|
|
// }
|
|
|
|
// // Emission
|
|
// if (this.active && psys.emissionRate) {
|
|
// var rate = 1.0 / psys.emissionRate;
|
|
// //issue #1201, prevent bursts of particles, due to too high emitCounter
|
|
// if (particles.length < psys.totalParticles)
|
|
// this.emitCounter += dt;
|
|
|
|
// while ((particles.length < psys.totalParticles) && (this.emitCounter > rate)) {
|
|
// this.emitParticle(_pos);
|
|
// this.emitCounter -= rate;
|
|
// }
|
|
|
|
// this.elapsed += dt;
|
|
// if (psys.duration !== -1 && psys.duration < this.elapsed) {
|
|
// psys.stopSystem();
|
|
// }
|
|
// }
|
|
|
|
// // Request buffer for particles
|
|
// let buffer = psys._assembler.getBuffer();
|
|
// let particleCount = particles.length;
|
|
// buffer.reset();
|
|
// buffer.request(particleCount * 4, particleCount * 6);
|
|
|
|
// // Fill up uvs
|
|
// if (particleCount > this._uvFilled) {
|
|
// this.updateUVs();
|
|
// }
|
|
|
|
// // Used to reduce memory allocation / creation within the loop
|
|
// let particleIdx = 0;
|
|
// while (particleIdx < particles.length) {
|
|
// // Reset temporary vectors
|
|
// _tpa.x = _tpa.y = _tpb.x = _tpb.y = _tpc.x = _tpc.y = 0;
|
|
|
|
// let particle = particles[particleIdx];
|
|
|
|
// // life
|
|
// particle.timeToLive -= dt;
|
|
// if (particle.timeToLive > 0) {
|
|
// // Mode A: gravity, direction, tangential accel & radial accel
|
|
// if (psys.emitterMode === cc.ParticleSystem.EmitterMode.GRAVITY) {
|
|
// let tmp = _tpc, radial = _tpa, tangential = _tpb;
|
|
|
|
// // radial acceleration
|
|
// if (particle.pos.x || particle.pos.y) {
|
|
// radial.set(particle.pos);
|
|
// radial.normalizeSelf();
|
|
// }
|
|
// tangential.set(radial);
|
|
// radial.mulSelf(particle.radialAccel);
|
|
|
|
// // tangential acceleration
|
|
// let newy = tangential.x;
|
|
// tangential.x = -tangential.y;
|
|
// tangential.y = newy;
|
|
|
|
// tangential.mulSelf(particle.tangentialAccel);
|
|
|
|
// tmp.set(radial);
|
|
// tmp.addSelf(tangential);
|
|
// tmp.addSelf(psys.gravity);
|
|
// tmp.mulSelf(dt);
|
|
// particle.dir.addSelf(tmp);
|
|
|
|
// tmp.set(particle.dir);
|
|
// tmp.mulSelf(dt);
|
|
// particle.pos.addSelf(tmp);
|
|
// }
|
|
// // Mode B: radius movement
|
|
// else {
|
|
// // Update the angle and radius of the particle.
|
|
// particle.angle += particle.degreesPerSecond * dt;
|
|
// particle.radius += particle.deltaRadius * dt;
|
|
|
|
// particle.pos.x = -Math.cos(particle.angle) * particle.radius;
|
|
// particle.pos.y = -Math.sin(particle.angle) * particle.radius;
|
|
// }
|
|
|
|
// // color
|
|
// particle.color.r += particle.deltaColor.r * dt;
|
|
// particle.color.g += particle.deltaColor.g * dt;
|
|
// particle.color.b += particle.deltaColor.b * dt;
|
|
// particle.color.a += particle.deltaColor.a * dt;
|
|
|
|
// // size
|
|
// particle.size += particle.deltaSize * dt;
|
|
// if (particle.size < 0) {
|
|
// particle.size = 0;
|
|
// }
|
|
|
|
// // angle
|
|
// particle.rotation += particle.deltaRotation * dt;
|
|
|
|
// // update values in quad buffer
|
|
// let newPos = _tpa;
|
|
// newPos.set(particle.pos);
|
|
// if (psys.positionType !== PositionType.GROUPED) {
|
|
// newPos.addSelf(particle.startPos);
|
|
// }
|
|
|
|
// let offset = FLOAT_PER_PARTICLE * particleIdx;
|
|
// this.updateParticleBuffer(particle, newPos, buffer, offset);
|
|
|
|
// // update particle counter
|
|
// ++particleIdx;
|
|
// } else {
|
|
// // life < 0
|
|
// let deadParticle = particles[particleIdx];
|
|
// if (particleIdx !== particles.length - 1) {
|
|
// particles[particleIdx] = particles[particles.length - 1];
|
|
// }
|
|
// pool.put(deadParticle);
|
|
// particles.length--;
|
|
// }
|
|
// }
|
|
|
|
// if (particles.length > 0) {
|
|
// buffer.uploadData();
|
|
// psys._assembler._ia._count = particles.length * 6;
|
|
// }
|
|
// else if (!this.active && !this.readyToPlay) {
|
|
// this.finished = true;
|
|
// psys._finishedSimulation();
|
|
// }
|
|
// }
|
|
}
|
|
|