Skip to content

Commit 4d63cf7

Browse files
committed
Added more particle emitter properties and linear interpolation for particle's life
1 parent 32786ac commit 4d63cf7

5 files changed

Lines changed: 133 additions & 54 deletions

File tree

v3/src/gameobjects/emitter/Particle.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ var Particle = new Class({
1616
this.scaleX = 1.0;
1717
this.scaleY = 1.0;
1818
this.life = 1.0;
19+
this.color = 0xFFFFFFFF;
20+
this.lifeStep = 1.0;
21+
this.normLifeStep = 1.0;
22+
23+
this.start = {
24+
tint: 0xFFFFFF,
25+
alpha: 1.0,
26+
scale: 1.0
27+
};
28+
29+
this.end = {
30+
tint: 0xFFFFFF,
31+
alpha: 1.0,
32+
scale: 1.0
33+
};
1934
},
2035

2136
reset: function (x, y)
@@ -29,7 +44,27 @@ var Particle = new Class({
2944
this.scaleX = 1.0;
3045
this.scaleY = 1.0;
3146
this.life = 1.0;
47+
this.color = 0xFFFFFFFF;
48+
this.lifeStep = 1.0;
49+
this.normLifeStep = 1.0;
50+
51+
this.start = {
52+
tint: 0xFFFFFF,
53+
alpha: 1.0,
54+
scale: 1.0
55+
};
56+
57+
this.end = {
58+
tint: 0xFFFFFF,
59+
alpha: 1.0,
60+
scale: 1.0
61+
};
3262
return this;
63+
},
64+
65+
isAlive: function ()
66+
{
67+
return this.lifeStep > 0;
3368
}
3469

3570
});

v3/src/gameobjects/emitter/ParticleEmitter.js

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,18 @@ var ParticleEmitter = new Class({
3333
this.alive = [];
3434
this.minSpeed = 0;
3535
this.maxSpeed = 0;
36+
this.minScale = 1.0;
37+
this.maxScale = 1.0;
38+
this.minAlpha = 1.0;
39+
this.maxAlpha = 1.0;
3640
this.minAngle = 0;
3741
this.maxAngle = 0;
42+
this.minPartAngle = 0;
43+
this.maxPartAngle = 0;
3844
this.gravityX = 0;
3945
this.gravityY = 0;
4046
this.life = 1.0;
47+
this.deathCallback = null;
4148
this.setTexture(texture, frame);
4249
this.setPosition(x, y);
4350
},
@@ -48,12 +55,30 @@ var ParticleEmitter = new Class({
4855
this.maxSpeed = max;
4956
},
5057

51-
setAngle: function (min, max)
58+
setEmitAngle: function (min, max)
5259
{
5360
this.minAngle = min;
5461
this.maxAngle = max;
5562
},
5663

64+
setScale: function (start, end)
65+
{
66+
this.minScale = start;
67+
this.maxScale = end;
68+
},
69+
70+
setAlpha: function (start, end)
71+
{
72+
this.minAlpha = start;
73+
this.maxAlpha = end;
74+
},
75+
76+
setAngle: function (min, max)
77+
{
78+
this.minPartAngle = min;
79+
this.maxPartAngle = max;
80+
},
81+
5782
setGravity: function (x, y)
5883
{
5984
this.gravityX = x;
@@ -84,6 +109,12 @@ var ParticleEmitter = new Class({
84109
return this.getAliveParticleCount() + this.getDeadParticleCount();
85110
},
86111

112+
onParticleDeath: function (callback)
113+
{
114+
if (typeof callback === 'function')
115+
this.deathCallback = callback;
116+
},
117+
87118
killAll: function ()
88119
{
89120
var dead = this.dead;
@@ -134,22 +165,34 @@ var ParticleEmitter = new Class({
134165
particle = new Particle(this.x, this.y);
135166
}
136167

168+
particle.rotation = Between(this.minPartAngle, this.maxPartAngle) * Math.PI / 180;
137169
particle.velocityX = vx;
138170
particle.velocityY = vy;
139-
particle.life = this.life;
171+
particle.life = Math.max(this.life, Number.MIN_VALUE);
172+
particle.lifeStep = particle.life;
173+
particle.start.scale = this.minScale;
174+
particle.end.scale = this.maxScale;
175+
particle.scaleX = this.minScale;
176+
particle.scaleY = this.minScale;
177+
particle.start.alpha = this.minAlpha;
178+
particle.end.alpha = this.maxAlpha;
179+
particle.color = (particle.color & 0x00FFFFFF) | (((this.minAlpha * 0xFF)|0) << 24);
140180
particle.index = this.alive.length;
141181

142182
this.alive.push(particle);
183+
184+
return particle;
143185
},
144186

145187
preUpdate: function (time, delta)
146188
{
147189
var dead = this.dead;
148190
var particles = this.alive;
149191
var length = particles.length;
150-
var step = delta / 1000;
151-
var gravityX = this.gravityX * step;
152-
var gravityY = this.gravityY * step;
192+
var emitterStep = (delta / 1000);
193+
var gravityX = this.gravityX * emitterStep;
194+
var gravityY = this.gravityY * emitterStep;
195+
var deathCallback = this.deathCallback;
153196

154197
/* Simulation */
155198
for (var index = 0; index < length; ++index)
@@ -158,19 +201,29 @@ var ParticleEmitter = new Class({
158201

159202
particle.velocityX += gravityX;
160203
particle.velocityY += gravityY;
161-
particle.x += particle.velocityX * step;
162-
particle.y += particle.velocityY * step;
163-
particle.rotation += particle.angularVelocity * step;
164-
particle.life -= step;
204+
particle.x += particle.velocityX * emitterStep;
205+
particle.y += particle.velocityY * emitterStep;
206+
particle.rotation += particle.angularVelocity * emitterStep;
207+
particle.normLifeStep = particle.lifeStep / particle.life;
208+
209+
var norm = 1.0 - particle.normLifeStep;
210+
var alphaf = (particle.end.alpha - particle.start.alpha) * norm + particle.start.alpha;
211+
var scale = (particle.end.scale - particle.start.scale) * norm + particle.start.scale;
165212

166-
if (particle.life <= 0)
213+
particle.scaleX = particle.scaleY = scale;
214+
particle.color = (particle.color & 0x00FFFFFF) | (((alphaf * 0xFF)|0) << 24);
215+
216+
if (particle.lifeStep <= 0)
167217
{
168-
let last = particles[length - 1];
218+
var last = particles[length - 1];
169219
particles[length - 1] = particle;
170220
particles[index] = last;
171221
index -= 1;
172222
length -= 1;
223+
if (deathCallback) deathCallback(particle);
173224
}
225+
particle.lifeStep -= emitterStep;
226+
174227
}
175228

176229
/* Cleanup */

v3/src/renderer/webgl/renderers/particlerenderer/ParticleRenderer.js

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,7 @@ var ParticleRenderer = new Class({
7272

7373
vertexBufferObject.addAttribute(shader.getAttribLocation('a_position'), 2, gl.FLOAT, false, CONST.VERTEX_SIZE, 0);
7474
vertexBufferObject.addAttribute(shader.getAttribLocation('a_tex_coord'), 2, gl.FLOAT, false, CONST.VERTEX_SIZE, 8);
75-
vertexBufferObject.addAttribute(shader.getAttribLocation('a_scale'), 2, gl.FLOAT, false, CONST.VERTEX_SIZE, 16);
76-
vertexBufferObject.addAttribute(shader.getAttribLocation('a_rotation'), 2, gl.FLOAT, false, CONST.VERTEX_SIZE, 24);
77-
vertexBufferObject.addAttribute(shader.getAttribLocation('a_color'), 4, gl.UNSIGNED_BYTE, true, CONST.VERTEX_SIZE, 28);
75+
vertexBufferObject.addAttribute(shader.getAttribLocation('a_color'), 4, gl.UNSIGNED_BYTE, true, CONST.VERTEX_SIZE, 16);
7876

7977
// Populate the index buffer only once
8078
for (var indexA = 0, indexB = 0; indexA < max; indexA += CONST.INDEX_COUNT, indexB += CONST.VERTEX_COUNT)
@@ -214,6 +212,8 @@ var ParticleRenderer = new Class({
214212
var particleCount = 0;
215213
var batchCount = Math.ceil(length / CONST.MAX);
216214
var renderTarget = emitter.renderTarget;
215+
var tempMatrix = this.tempMatrix;
216+
var tempMatrixMatrix = tempMatrix.matrix;
217217
var particleOffset = 0;
218218

219219
if (length === 0) return;
@@ -226,64 +226,67 @@ var ParticleRenderer = new Class({
226226
for (var index = 0; index < batchSize; ++index)
227227
{
228228
var particle = particles[particleOffset + index];
229-
var x = particle.x - ox;
230-
var y = particle.y - oy;
229+
var x = -ox;
230+
var y = -oy;
231231
var scaleX = particle.scaleX;
232232
var scaleY = particle.scaleY;
233233
var rotation = particle.rotation;
234-
var color = 0xFFFFFFFF;
234+
var color = particle.color;
235235
var xw = x + width;
236236
var yh = y + height;
237-
var tx0 = x * cma + y * cmc + cme;
238-
var ty0 = x * cmb + y * cmd + cmf;
239-
var tx1 = x * cma + yh * cmc + cme;
240-
var ty1 = x * cmb + yh * cmd + cmf;
241-
var tx2 = xw * cma + yh * cmc + cme;
242-
var ty2 = xw * cmb + yh * cmd + cmf;
243-
var tx3 = xw * cma + y * cmc + cme;
244-
var ty3 = xw * cmb + y * cmd + cmf;
245-
246-
vtxOffset = data.allocate(32);
237+
238+
tempMatrix.applyITRS(particle.x, particle.y, rotation, scaleX, scaleY);
239+
240+
var sra = tempMatrixMatrix[0];
241+
var srb = tempMatrixMatrix[1];
242+
var src = tempMatrixMatrix[2];
243+
var srd = tempMatrixMatrix[3];
244+
var sre = tempMatrixMatrix[4];
245+
var srf = tempMatrixMatrix[5];
246+
var mva = sra * cma + srb * cmc;
247+
var mvb = sra * cmb + srb * cmd;
248+
var mvc = src * cma + srd * cmc;
249+
var mvd = src * cmb + srd * cmd;
250+
var mve = sre * cma + srf * cmc + cme;
251+
var mvf = sre * cmb + srf * cmd + cmf;
252+
var tx0 = x * mva + y * mvc + mve;
253+
var ty0 = x * mvb + y * mvd + mvf;
254+
var tx1 = x * mva + yh * mvc + mve;
255+
var ty1 = x * mvb + yh * mvd + mvf;
256+
var tx2 = xw * mva + yh * mvc + mve;
257+
var ty2 = xw * mvb + yh * mvd + mvf;
258+
var tx3 = xw * mva + y * mvc + mve;
259+
var ty3 = xw * mvb + y * mvd + mvf;
260+
261+
vtxOffset = data.allocate(20);
247262
elementCount += 6;
248263

249264
// Top Left
250265
vbF32[vtxOffset++] = tx0;
251266
vbF32[vtxOffset++] = ty0;
252267
vbF32[vtxOffset++] = u0;
253268
vbF32[vtxOffset++] = v0;
254-
vbF32[vtxOffset++] = scaleX;
255-
vbF32[vtxOffset++] = scaleY;
256-
vbF32[vtxOffset++] = rotation;
257269
vbU32[vtxOffset++] = color;
258270

259271
// Bottom Left
260272
vbF32[vtxOffset++] = tx1;
261273
vbF32[vtxOffset++] = ty1;
262274
vbF32[vtxOffset++] = u1;
263275
vbF32[vtxOffset++] = v1;
264-
vbF32[vtxOffset++] = scaleX;
265-
vbF32[vtxOffset++] = scaleY;
266-
vbF32[vtxOffset++] = rotation;
267276
vbU32[vtxOffset++] = color;
268277

269278
// Bottom Right
270279
vbF32[vtxOffset++] = tx2;
271280
vbF32[vtxOffset++] = ty2;
272281
vbF32[vtxOffset++] = u2;
273282
vbF32[vtxOffset++] = v2;
274-
vbF32[vtxOffset++] = scaleX;
275-
vbF32[vtxOffset++] = scaleY;
276-
vbF32[vtxOffset++] = rotation;
277283
vbU32[vtxOffset++] = color;
278284

279285
// Top Right
280286
vbF32[vtxOffset++] = tx3;
281287
vbF32[vtxOffset++] = ty3;
282288
vbF32[vtxOffset++] = u3;
283289
vbF32[vtxOffset++] = v3;
284-
vbF32[vtxOffset++] = scaleX;
285-
vbF32[vtxOffset++] = scaleY;
286-
vbF32[vtxOffset++] = rotation;
287290
vbU32[vtxOffset++] = color;
288291
}
289292
particleOffset += batchSize;

v3/src/renderer/webgl/renderers/particlerenderer/const.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ var CONST = {
44
{
55
float position[2];
66
float tex_coord[2];
7-
float scale[2];
8-
float rotation;
97
unsigned int color;
108
};
119
*/
12-
VERTEX_SIZE: 32, /* sizeof(v) */
10+
VERTEX_SIZE: 20, /* sizeof(v) */
1311
INDEX_SIZE: 2,
1412
VERTEX_COUNT: 4,
1513
INDEX_COUNT: 6,
16-
COMPONENT32_COUNT: 8, /* sizeof(v) / 4 */
14+
COMPONENT32_COUNT: 5, /* sizeof(v) / 4 */
1715
MAX: 16000
1816

1917
};

v3/src/renderer/webgl/shaders/ParticleShader.js

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,14 @@ module.exports = {
55
66
attribute vec2 a_position;
77
attribute vec2 a_tex_coord;
8-
attribute vec2 a_scale;
9-
attribute float a_rotation;
108
attribute vec4 a_color;
119
1210
varying vec4 v_color;
1311
varying vec2 v_tex_coord;
1412
1513
void main()
1614
{
17-
vec2 position = vec2(0.0, 0.0);
18-
float cos_rot = cos(a_rotation);
19-
float sin_rot = sin(a_rotation);
20-
21-
position.x = a_position.x * cos_rot - a_position.y * sin_rot;
22-
position.y = a_position.x * sin_rot + a_position.y * cos_rot;
23-
position = position * a_scale;
24-
25-
gl_Position = u_view_matrix * vec4(position, 1.0, 1.0);
15+
gl_Position = u_view_matrix * vec4(a_position, 1.0, 1.0);
2616
2717
v_color = a_color;
2818
v_tex_coord = a_tex_coord;

0 commit comments

Comments
 (0)