Skip to content

Commit 95b0532

Browse files
committed
Emitter.setScale has a new 'rate' parameter which allows particles to change in scale over time, using any Easing value or timescale.
Emitter.setAlpha has a new 'rate' parameter which allows particles to change alpha over time, using any Easing value or timescale. Emitter.bringToTop and Emitter.sendToBack are booleans that let you optionally set the display order of the Particle when emitted.
1 parent ff7dd65 commit 95b0532

3 files changed

Lines changed: 205 additions & 34 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ New Features
110110
* Emitter.setScale allows you to quickly set the min and max scale values.
111111
* Emitter.blendMode lets you set the blendMode of any emitted Particle (needs a browser that supports canvas blend modes)
112112
* Group.customSort allows you to sort the Group children based on your own sort function.
113+
* Emitter.setScale has a new 'rate' parameter which allows particles to change in scale over time, using any Easing value or timescale.
114+
* Emitter.setAlpha has a new 'rate' parameter which allows particles to change alpha over time, using any Easing value or timescale.
115+
* Emitter.bringToTop and Emitter.sendToBack are booleans that let you optionally set the display order of the Particle when emitted.
113116

114117

115118
Bug Fixes

src/gameobjects/Particle.js

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,15 @@ Phaser.Particle = function (game, x, y, key, frame) {
2121

2222
Phaser.Sprite.call(this, game, x, y, key, frame);
2323

24-
}
24+
this.autoScale = false;
25+
this.scaleData = null;
26+
this._s = 0;
27+
28+
this.autoAlpha = false;
29+
this.alphaData = null;
30+
this._a = 0;
31+
32+
};
2533

2634
Phaser.Particle.prototype = Object.create(Phaser.Sprite.prototype);
2735
Phaser.Particle.prototype.constructor = Phaser.Particle;
@@ -34,6 +42,94 @@ Phaser.Particle.prototype.constructor = Phaser.Particle;
3442
*/
3543
Phaser.Particle.prototype.update = function() {
3644

45+
if (this.autoScale)
46+
{
47+
this._s--;
48+
49+
if (this._s)
50+
{
51+
this.scale.set(this.scaleData[this._s].v);
52+
}
53+
else
54+
{
55+
this.autoScale = false;
56+
}
57+
}
58+
59+
if (this.autoAlpha)
60+
{
61+
this._a--;
62+
63+
if (this._a)
64+
{
65+
this.alpha = this.alphaData[this._a].v;
66+
}
67+
else
68+
{
69+
this.autoAlpha = false;
70+
}
71+
}
72+
73+
};
74+
75+
Phaser.Particle.prototype.onEmit = function() {
76+
};
77+
78+
Phaser.Particle.prototype.setAlphaData = function(data) {
79+
80+
this.alphaData = data;
81+
this._a = data.length - 1;
82+
this.alpha = this.alphaData[this._a].v;
83+
this.autoAlpha = true;
84+
85+
};
86+
87+
Phaser.Particle.prototype.setScaleData = function(data) {
88+
89+
this.scaleData = data;
90+
this._s = data.length - 1;
91+
this.scale.set(this.scaleData[this._s].v);
92+
this.autoScale = true;
93+
94+
};
95+
96+
/**
97+
* Resets the Particle. This places the Particle at the given x/y world coordinates and then
98+
* sets alive, exists, visible and renderable all to true. Also resets the outOfBounds state and health values.
99+
* If the Particle has a physics body that too is reset.
100+
*
101+
* @method Phaser.Particle#reset
102+
* @memberof Phaser.Particle
103+
* @param {number} x - The x coordinate (in world space) to position the Particle at.
104+
* @param {number} y - The y coordinate (in world space) to position the Particle at.
105+
* @param {number} [health=1] - The health to give the Particle.
106+
* @return (Phaser.Particle) This instance.
107+
*/
108+
Phaser.Particle.prototype.reset = function(x, y, health) {
109+
110+
if (typeof health === 'undefined') { health = 1; }
111+
112+
this.world.setTo(x, y);
113+
this.position.x = x;
114+
this.position.y = y;
115+
this.alive = true;
116+
this.exists = true;
117+
this.visible = true;
118+
this.renderable = true;
119+
this._outOfBoundsFired = false;
120+
121+
this.health = health;
122+
123+
if (this.body)
124+
{
125+
this.body.reset(x, y, false, false);
126+
}
127+
128+
this._cache[4] = 1;
129+
130+
this.autoScale = false;
131+
this.autoAlpha = false;
37132

133+
return this;
38134

39135
};

src/particles/arcade/Emitter.js

Lines changed: 105 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ Phaser.Particles.Arcade.Emitter = function (game, x, y, maxParticles) {
7676
*/
7777
this.maxParticleScale = 1;
7878

79+
/**
80+
* @property {array} scaleData - An array of the calculated scale easing data applied to particles with scaleRates > 0.
81+
*/
82+
this.scaleData = null;
83+
7984
/**
8085
* @property {number} minRotation - The minimum possible angular velocity of a particle.
8186
* @default
@@ -100,6 +105,11 @@ Phaser.Particles.Arcade.Emitter = function (game, x, y, maxParticles) {
100105
*/
101106
this.maxParticleAlpha = 1;
102107

108+
/**
109+
* @property {array} alphaData - An array of the calculated alpha easing data applied to particles with alphaRates > 0.
110+
*/
111+
this.alphaData = null;
112+
103113
/**
104114
* @property {number} gravity - Sets the `body.gravity.y` of each particle sprite to this value on launch.
105115
* @default
@@ -174,6 +184,28 @@ Phaser.Particles.Arcade.Emitter = function (game, x, y, maxParticles) {
174184
*/
175185
this.emitY = y;
176186

187+
/**
188+
* @property {boolean} autoScale - When a new Particle is emitted this controls if it will automatically scale in size. Use Emitter.setScale to configure.
189+
*/
190+
this.autoScale = false;
191+
192+
/**
193+
* @property {boolean} autoAlpha - When a new Particle is emitted this controls if it will automatically change alpha. Use Emitter.setAlpha to configure.
194+
*/
195+
this.autoAlpha = false;
196+
197+
/**
198+
* @property {boolean} particleBringToTop - If this is `true` then when the Particle is emitted it will be bought to the top of the Emitters display list.
199+
* @default
200+
*/
201+
this.particleBringToTop = false;
202+
203+
/**
204+
* @property {boolean} particleSendToBack - If this is `true` then when the Particle is emitted it will be sent to the back of the Emitters display list.
205+
* @default
206+
*/
207+
this.particleSendToBack = false;
208+
177209
/**
178210
* @property {number} _quantity - Internal helper for deciding how many particles to launch.
179211
* @private
@@ -398,21 +430,11 @@ Phaser.Particles.Arcade.Emitter.prototype.emitParticle = function () {
398430

399431
var particle = this.getFirstExists(false);
400432

401-
if (particle == null)
433+
if (particle === null)
402434
{
403435
return;
404436
}
405437

406-
particle.angle = 0;
407-
particle.bringToTop();
408-
409-
if (this.minParticleScale !== 1 || this.maxParticleScale !== 1)
410-
{
411-
particle.scale.set(this.game.rnd.realInRange(this.minParticleScale, this.maxParticleScale));
412-
}
413-
414-
particle.body.updateBounds();
415-
416438
if (this.width > 1 || this.height > 1)
417439
{
418440
particle.reset(this.game.rnd.integerInRange(this.left, this.right), this.game.rnd.integerInRange(this.top, this.bottom));
@@ -422,38 +444,28 @@ Phaser.Particles.Arcade.Emitter.prototype.emitParticle = function () {
422444
particle.reset(this.emitX, this.emitY);
423445
}
424446

447+
particle.angle = 0;
425448
particle.lifespan = this.lifespan;
426449

427-
particle.body.bounce.setTo(this.bounce.x, this.bounce.y);
428-
429-
if (this.minParticleSpeed.x !== this.maxParticleSpeed.x)
450+
if (this.particleBringToTop)
430451
{
431-
particle.body.velocity.x = this.game.rnd.integerInRange(this.minParticleSpeed.x, this.maxParticleSpeed.x);
452+
this.bringToTop(particle);
432453
}
433-
else
454+
else if (this.particleSendToBack)
434455
{
435-
particle.body.velocity.x = this.minParticleSpeed.x;
456+
this.sendToBack(particle);
436457
}
437458

438-
if (this.minParticleSpeed.y !== this.maxParticleSpeed.y)
459+
if (this.autoScale)
439460
{
440-
particle.body.velocity.y = this.game.rnd.integerInRange(this.minParticleSpeed.y, this.maxParticleSpeed.y);
461+
particle.setScaleData(this.scaleData);
441462
}
442463
else
443464
{
444-
particle.body.velocity.y = this.minParticleSpeed.y;
445-
}
446-
447-
if (this.minRotation !== this.maxRotation)
448-
{
449-
particle.body.angularVelocity = this.game.rnd.integerInRange(this.minRotation, this.maxRotation);
450-
}
451-
else if (this.minRotation !== 0)
452-
{
453-
particle.body.angularVelocity = this.minRotation;
465+
particle.scale.set(this.game.rnd.realInRange(this.minParticleScale, this.maxParticleScale));
454466
}
455467

456-
if (typeof this._frames === 'object')
468+
if (Array.isArray(this._frames === 'object'))
457469
{
458470
particle.frame = this.game.rnd.pick(this._frames);
459471
}
@@ -462,18 +474,34 @@ Phaser.Particles.Arcade.Emitter.prototype.emitParticle = function () {
462474
particle.frame = this._frames;
463475
}
464476

465-
if (this.minParticleAlpha !== 1 || this.maxParticleAlpha !== 1)
477+
if (this.autoAlpha)
478+
{
479+
particle.setAlphaData(this.alphaData);
480+
}
481+
else
466482
{
467483
particle.alpha = this.game.rnd.realInRange(this.minParticleAlpha, this.maxParticleAlpha);
468484
}
469485

470486
particle.blendMode = this.blendMode;
471487

488+
particle.body.updateBounds();
489+
490+
particle.body.bounce.setTo(this.bounce.x, this.bounce.y);
491+
492+
particle.body.velocity.x = this.game.rnd.integerInRange(this.minParticleSpeed.x, this.maxParticleSpeed.x);
493+
particle.body.velocity.y = this.game.rnd.integerInRange(this.minParticleSpeed.y, this.maxParticleSpeed.y);
494+
particle.body.angularVelocity = this.game.rnd.integerInRange(this.minRotation, this.maxRotation);
495+
472496
particle.body.gravity.y = this.gravity;
497+
473498
particle.body.drag.x = this.particleDrag.x;
474499
particle.body.drag.y = this.particleDrag.y;
500+
475501
particle.body.angularDrag = this.angularDrag;
476502

503+
particle.onEmit();
504+
477505
};
478506

479507
/**
@@ -540,35 +568,79 @@ Phaser.Particles.Arcade.Emitter.prototype.setRotation = function (min, max) {
540568

541569
/**
542570
* A more compact way of setting the alpha constraints of the particles.
571+
* The rate parameter, if set to a value above zero, lets you set the speed at which the Particle change in alpha from min to max.
572+
* If rate is zero, which is the default, the particle won't change alpha - instead it will pick a random alpha between min and max on emit.
543573
*
544574
* @method Phaser.Particles.Arcade.Emitter#setAlpha
545575
* @param {number} [min=1] - The minimum value for this range.
546576
* @param {number} [max=1] - The maximum value for this range.
577+
* @param {number} [rate=0] - The rate (in ms) at which the particles will change in alpha from min to max, or set to zero to pick a random alpha between the two.
578+
* @param {number} [ease=Phaser.Easing.Linear.None] - If you've set a rate > 0 this is the easing formula applied between the min and max values.
579+
* @param {boolean} [yoyo=false] - If you've set a rate > 0 you can set if the ease will yoyo or not (i.e. ease back to its original values)
547580
*/
548-
Phaser.Particles.Arcade.Emitter.prototype.setAlpha = function (min, max) {
581+
Phaser.Particles.Arcade.Emitter.prototype.setAlpha = function (min, max, rate, ease, yoyo) {
549582

550583
if (typeof min === 'undefined') { min = 1; }
551584
if (typeof max === 'undefined') { max = 1; }
585+
if (typeof rate === 'undefined') { rate = 0; }
586+
if (typeof ease === 'undefined') { ease = Phaser.Easing.Linear.None; }
587+
if (typeof yoyo === 'undefined') { yoyo = false; }
552588

553589
this.minParticleAlpha = min;
554590
this.maxParticleAlpha = max;
591+
this.autoAlpha = false;
592+
593+
if (rate > 0)
594+
{
595+
var tweenData = { v: min };
596+
var tween = this.game.make.tween(tweenData).to( { v: max }, rate, ease);
597+
tween.yoyo(yoyo);
598+
599+
this.alphaData = tween.generateData(60);
600+
601+
// Inverse it so we don't have to do array length look-ups in Particle update loops
602+
this.alphaData.reverse();
603+
this.autoAlpha = true;
604+
}
555605

556606
};
557607

558608
/**
559609
* A more compact way of setting the scale constraints of the particles.
610+
* The rate parameter, if set to a value above zero, lets you set the speed and ease which the Particle uses to change in scale from min to max.
611+
* If rate is zero, which is the default, the particle won't change scale - instead it will pick a random scale between min and max on emit.
560612
*
561613
* @method Phaser.Particles.Arcade.Emitter#setScale
562614
* @param {number} [min=1] - The minimum value for this range.
563615
* @param {number} [max=1] - The maximum value for this range.
616+
* @param {number} [rate=0] - The rate (in ms) at which the particles will change in scale from min to max, or set to zero to pick a random size between the two.
617+
* @param {number} [ease=Phaser.Easing.Linear.None] - If you've set a rate > 0 this is the easing formula applied between the min and max values.
618+
* @param {boolean} [yoyo=false] - If you've set a rate > 0 you can set if the ease will yoyo or not (i.e. ease back to its original values)
564619
*/
565-
Phaser.Particles.Arcade.Emitter.prototype.setScale = function (min, max) {
620+
Phaser.Particles.Arcade.Emitter.prototype.setScale = function (min, max, rate, ease, yoyo) {
566621

567622
if (typeof min === 'undefined') { min = 1; }
568623
if (typeof max === 'undefined') { max = 1; }
624+
if (typeof rate === 'undefined') { rate = 0; }
625+
if (typeof ease === 'undefined') { ease = Phaser.Easing.Linear.None; }
626+
if (typeof yoyo === 'undefined') { yoyo = false; }
569627

570628
this.minParticleScale = min;
571629
this.maxParticleScale = max;
630+
this.autoScale = false;
631+
632+
if (rate > 0)
633+
{
634+
var tweenData = { v: min };
635+
var tween = this.game.make.tween(tweenData).to( { v: max }, rate, ease);
636+
tween.yoyo(yoyo);
637+
638+
this.scaleData = tween.generateData(60);
639+
640+
// Inverse it so we don't have to do array length look-ups in Particle update loops
641+
this.scaleData.reverse();
642+
this.autoScale = true;
643+
}
572644

573645
};
574646

0 commit comments

Comments
 (0)