mirror of
https://github.com/photonstorm/phaser
synced 2025-01-11 12:48:50 +00:00
525730dbb1
- Created a description of the object handed to the function setAnim - Added the property anim to ParticleEmitterConfig - Changed the parameters description of setAnim to better match
3919 lines
118 KiB
JavaScript
3919 lines
118 KiB
JavaScript
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = require('../../utils/Class');
|
|
var Components = require('../components');
|
|
var ComponentsToJSON = require('../components/ToJSON');
|
|
var CopyFrom = require('../../geom/rectangle/CopyFrom');
|
|
var DeathZone = require('./zones/DeathZone');
|
|
var EdgeZone = require('./zones/EdgeZone');
|
|
var EmitterColorOp = require('./EmitterColorOp');
|
|
var EmitterOp = require('./EmitterOp');
|
|
var Events = require('./events');
|
|
var GameObject = require('../GameObject');
|
|
var GetFastValue = require('../../utils/object/GetFastValue');
|
|
var GetRandom = require('../../utils/array/GetRandom');
|
|
var GravityWell = require('./GravityWell');
|
|
var HasAny = require('../../utils/object/HasAny');
|
|
var HasValue = require('../../utils/object/HasValue');
|
|
var Inflate = require('../../geom/rectangle/Inflate');
|
|
var List = require('../../structs/List');
|
|
var MergeRect = require('../../geom/rectangle/MergeRect');
|
|
var Particle = require('./Particle');
|
|
var RandomZone = require('./zones/RandomZone');
|
|
var Rectangle = require('../../geom/rectangle/Rectangle');
|
|
var RectangleToRectangle = require('../../geom/intersects/RectangleToRectangle');
|
|
var Remove = require('../../utils/array/Remove');
|
|
var Render = require('./ParticleEmitterRender');
|
|
var StableSort = require('../../utils/array/StableSort');
|
|
var TransformMatrix = require('../components/TransformMatrix');
|
|
var Vector2 = require('../../math/Vector2');
|
|
var Wrap = require('../../math/Wrap');
|
|
var ParticleBounds = require('./ParticleBounds');
|
|
|
|
/**
|
|
* Names of simple configuration properties.
|
|
*
|
|
* @ignore
|
|
*/
|
|
var configFastMap = [
|
|
'active',
|
|
'advance',
|
|
'blendMode',
|
|
'colorEase',
|
|
'deathCallback',
|
|
'deathCallbackScope',
|
|
'duration',
|
|
'emitCallback',
|
|
'emitCallbackScope',
|
|
'follow',
|
|
'frequency',
|
|
'gravityX',
|
|
'gravityY',
|
|
'maxAliveParticles',
|
|
'maxParticles',
|
|
'name',
|
|
'emitting',
|
|
'particleBringToTop',
|
|
'particleClass',
|
|
'radial',
|
|
'sortCallback',
|
|
'sortOrderAsc',
|
|
'sortProperty',
|
|
'stopAfter',
|
|
'tintFill',
|
|
'timeScale',
|
|
'trackVisible',
|
|
'visible'
|
|
];
|
|
|
|
/**
|
|
* Names of complex configuration properties.
|
|
*
|
|
* @ignore
|
|
*/
|
|
var configOpMap = [
|
|
'accelerationX',
|
|
'accelerationY',
|
|
'alpha',
|
|
'angle',
|
|
'bounce',
|
|
'color',
|
|
'delay',
|
|
'hold',
|
|
'lifespan',
|
|
'maxVelocityX',
|
|
'maxVelocityY',
|
|
'moveToX',
|
|
'moveToY',
|
|
'quantity',
|
|
'rotate',
|
|
'scaleX',
|
|
'scaleY',
|
|
'speedX',
|
|
'speedY',
|
|
'tint',
|
|
'x',
|
|
'y'
|
|
];
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Particle Emitter is a special kind of Game Object that controls a pool of {@link Phaser.GameObjects.Particles.Particle Particles}.
|
|
*
|
|
* Particle Emitters are created via a configuration object. The properties of this object
|
|
* can be specified in a variety of formats, given you plenty of scope over the values they
|
|
* return, leading to complex visual effects. Here are the different forms of configuration
|
|
* value you can give:
|
|
*
|
|
* ## An explicit static value:
|
|
*
|
|
* ```js
|
|
* x: 400
|
|
* ```
|
|
*
|
|
* The x value will always be 400 when the particle is spawned.
|
|
*
|
|
* ## A random value:
|
|
*
|
|
* ```js
|
|
* x: [ 100, 200, 300, 400 ]
|
|
* ```
|
|
*
|
|
* The x value will be one of the 4 elements in the given array, picked at random on emission.
|
|
*
|
|
* ## A custom callback:
|
|
*
|
|
* ```js
|
|
* x: (particle, key, t, value) => {
|
|
* return value + 50;
|
|
* }
|
|
* ```
|
|
*
|
|
* The x value is the result of calling this function. This is only used when the
|
|
* particle is emitted, so it provides it's initial starting value. It is not used
|
|
* when the particle is updated (see the onUpdate callback for that)
|
|
*
|
|
* ## A start / end object:
|
|
*
|
|
* This allows you to control the change in value between the given start and
|
|
* end parameters over the course of the particles lifetime:
|
|
*
|
|
* ```js
|
|
* scale: { start: 0, end: 1 }
|
|
* ```
|
|
*
|
|
* The particle scale will start at 0 when emitted and ease to a scale of 1
|
|
* over the course of its lifetime. You can also specify the ease function
|
|
* used for this change (the default is Linear):
|
|
*
|
|
* ```js
|
|
* scale: { start: 0, end: 1, ease: 'bounce.out' }
|
|
* ```
|
|
*
|
|
* ## A start / end random object:
|
|
*
|
|
* The start and end object can have an optional `random` parameter.
|
|
* This forces it to pick a random value between the two values and use
|
|
* this as the starting value, then easing to the 'end' parameter over
|
|
* its lifetime.
|
|
*
|
|
* ```js
|
|
* scale: { start: 4, end: 0.5, random: true }
|
|
* ```
|
|
*
|
|
* The particle will start with a random scale between 0.5 and 4 and then
|
|
* scale to the end value over its lifetime. You can combine the above
|
|
* with the `ease` parameter as well to control the value easing.
|
|
*
|
|
* ## An interpolation object:
|
|
*
|
|
* You can provide an array of values which will be used for interpolation
|
|
* during the particles lifetime. You can also define the interpolation
|
|
* function to be used. There are three provided: `linear` (the default),
|
|
* `bezier` and `catmull`, or you can provide your own function.
|
|
*
|
|
* ```js
|
|
* x: { values: [ 50, 500, 200, 800 ], interpolation: 'catmull' }
|
|
* ```
|
|
*
|
|
* The particle scale will interpolate from 50 when emitted to 800 via the other
|
|
* points over the course of its lifetime. You can also specify an ease function
|
|
* used to control the rate of change through the values (the default is Linear):
|
|
*
|
|
* ```js
|
|
* x: { values: [ 50, 500, 200, 800 ], interpolation: 'catmull', ease: 'bounce.out }
|
|
* ```
|
|
*
|
|
* ## A stepped emitter object:
|
|
*
|
|
* The `steps` parameter allows you to control the placement of sequential
|
|
* particles across the start-end range:
|
|
*
|
|
* ```js
|
|
* x: { steps: 32, start: 0, end: 576 }
|
|
* ```
|
|
*
|
|
* Here we have a range of 576 (start to end). This is divided into 32 steps.
|
|
*
|
|
* The first particle will emit at the x position of 0. The next will emit
|
|
* at the next 'step' along, which would be 18. The following particle will emit
|
|
* at the next step, which is 36, and so on. Because the range of 576 has been
|
|
* divided by 32, creating 18 pixels steps. When a particle reaches the 'end'
|
|
* value the next one will start from the beginning again.
|
|
*
|
|
* ## A stepped emitter object with yoyo:
|
|
*
|
|
* You can add the optional `yoyo` property to a stepped object:
|
|
*
|
|
* ```js
|
|
* x: { steps: 32, start: 0, end: 576, yoyo: true }
|
|
* ```
|
|
*
|
|
* As with the stepped emitter, particles are emitted in sequence, from 'start'
|
|
* to 'end' in step sized jumps. Normally, when a stepped emitter reaches the
|
|
* end it snaps around to the start value again. However, if you provide the 'yoyo'
|
|
* parameter then when it reaches the end it will reverse direction and start
|
|
* emitting back down to 'start' again. Depending on the effect you require this
|
|
* can often look better.
|
|
*
|
|
* ## A min / max object:
|
|
*
|
|
* This allows you to pick a random float value between the min and max properties:
|
|
*
|
|
* ```js
|
|
* x: { min: 100, max: 700 }
|
|
* ```
|
|
*
|
|
* The x value will be a random float between min and max.
|
|
*
|
|
* You can force it select an integer by setting the 'int' flag:
|
|
*
|
|
* ```js
|
|
* x: { min: 100, max: 700, int: true }
|
|
* ```
|
|
*
|
|
* Or, you could use the 'random' array approach (see below)
|
|
*
|
|
* ## A random object:
|
|
*
|
|
* This allows you to pick a random integer value between the first and second array elements:
|
|
*
|
|
* ```js
|
|
* x: { random: [ 100, 700 ] }
|
|
* ```
|
|
*
|
|
* The x value will be a random integer between 100 and 700 as it takes the first
|
|
* element in the 'random' array as the 'min' value and the 2nd element as the 'max' value.
|
|
*
|
|
* ## Custom onEmit and onUpdate callbacks:
|
|
*
|
|
* If the above won't give you the effect you're after, you can provide your own
|
|
* callbacks that will be used when the particle is both emitted and updated:
|
|
*
|
|
* ```js
|
|
* x: {
|
|
* onEmit: (particle, key, t, value) => {
|
|
* return value;
|
|
* },
|
|
* onUpdate: (particle, key, t, value) => {
|
|
* return value;
|
|
* }
|
|
* }
|
|
* ```
|
|
*
|
|
* You can provide either one or both functions. The `onEmit` is called at the
|
|
* start of the particles life and defines the value of the property on birth.
|
|
*
|
|
* The `onUpdate` function is called every time the Particle Emitter updates
|
|
* until the particle dies. Both must return a value.
|
|
*
|
|
* The properties are:
|
|
*
|
|
* particle - A reference to the Particle instance.
|
|
* key - The string based key of the property, i.e. 'x' or 'lifespan'.
|
|
* t - The current normalized lifetime of the particle, between 0 (birth) and 1 (death).
|
|
* value - The current property value. At a minimum you should return this.
|
|
*
|
|
* By using the above configuration options you have an unlimited about of
|
|
* control over how your particles behave.
|
|
*
|
|
* ## v3.55 Differences
|
|
*
|
|
* Prior to v3.60 Phaser used a `ParticleEmitterManager`. This was removed in v3.60
|
|
* and now calling `this.add.particles` returns a `ParticleEmitter` instance instead.
|
|
*
|
|
* In order to streamline memory and the display list we have removed the
|
|
* `ParticleEmitterManager` entirely. When you call `this.add.particles` you're now
|
|
* creating a `ParticleEmitter` instance, which is being added directly to the
|
|
* display list and can be manipulated just like any other Game Object, i.e.
|
|
* scaled, rotated, positioned, added to a Container, etc. It now extends the
|
|
* `GameObject` base class, meaning it's also an event emitter, which allowed us
|
|
* to create some handy new events for particles.
|
|
*
|
|
* So, to create an emitter, you now give it an xy coordinate, a texture and an
|
|
* emitter configuration object (you can also set this later, but most commonly
|
|
* you'd do it on creation). I.e.:
|
|
*
|
|
* ```js
|
|
* const emitter = this.add.particles(100, 300, 'flares', {
|
|
* frame: 'red',
|
|
* angle: { min: -30, max: 30 },
|
|
* speed: 150
|
|
* });
|
|
* ```
|
|
*
|
|
* This will create a 'red flare' emitter at 100 x 300.
|
|
*
|
|
* Please update your code to ensure it adheres to the new function signatures.
|
|
*
|
|
* @class ParticleEmitter
|
|
* @extends Phaser.GameObjects.GameObject
|
|
* @memberof Phaser.GameObjects.Particles
|
|
* @constructor
|
|
* @since 3.60.0
|
|
*
|
|
* @extends Phaser.GameObjects.Components.AlphaSingle
|
|
* @extends Phaser.GameObjects.Components.BlendMode
|
|
* @extends Phaser.GameObjects.Components.Depth
|
|
* @extends Phaser.GameObjects.Components.Mask
|
|
* @extends Phaser.GameObjects.Components.Pipeline
|
|
* @extends Phaser.GameObjects.Components.PostPipeline
|
|
* @extends Phaser.GameObjects.Components.ScrollFactor
|
|
* @extends Phaser.GameObjects.Components.Texture
|
|
* @extends Phaser.GameObjects.Components.Transform
|
|
* @extends Phaser.GameObjects.Components.Visible
|
|
*
|
|
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
|
|
* @param {number} [x] - The horizontal position of this Game Object in the world.
|
|
* @param {number} [y] - The vertical position of this Game Object in the world.
|
|
* @param {(string|Phaser.Textures.Texture)} [texture] - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager.
|
|
* @param {Phaser.Types.GameObjects.Particles.ParticleEmitterConfig} [config] - Settings for this emitter.
|
|
*/
|
|
var ParticleEmitter = new Class({
|
|
|
|
Extends: GameObject,
|
|
|
|
Mixins: [
|
|
Components.AlphaSingle,
|
|
Components.BlendMode,
|
|
Components.Depth,
|
|
Components.Mask,
|
|
Components.Pipeline,
|
|
Components.PostPipeline,
|
|
Components.ScrollFactor,
|
|
Components.Texture,
|
|
Components.Transform,
|
|
Components.Visible,
|
|
Render
|
|
],
|
|
|
|
initialize:
|
|
|
|
function ParticleEmitter (scene, x, y, texture, config)
|
|
{
|
|
GameObject.call(this, scene, 'ParticleEmitter');
|
|
|
|
/**
|
|
* The Particle Class which will be emitted by this Emitter.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleClass
|
|
* @type {function}
|
|
* @default Phaser.GameObjects.Particles.Particle
|
|
* @since 3.0.0
|
|
* @see Phaser.Types.GameObjects.Particles.ParticleClassConstructor
|
|
*/
|
|
this.particleClass = Particle;
|
|
|
|
/**
|
|
* An internal object holding all of the EmitterOp instances.
|
|
*
|
|
* These are populated as part of the Emitter configuration parsing.
|
|
*
|
|
* You typically do not access them directly, but instead use the
|
|
* provided getters and setters on this class, such as `ParticleEmitter.speedX` etc.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#ops
|
|
* @type {Phaser.Types.GameObjects.Particles.ParticleEmitterOps}
|
|
* @since 3.60.0
|
|
*/
|
|
this.ops = {
|
|
accelerationX: new EmitterOp('accelerationX', 0),
|
|
accelerationY: new EmitterOp('accelerationY', 0),
|
|
alpha: new EmitterOp('alpha', 1),
|
|
angle: new EmitterOp('angle', { min: 0, max: 360 }, true),
|
|
bounce: new EmitterOp('bounce', 0),
|
|
color: new EmitterColorOp('color'),
|
|
delay: new EmitterOp('delay', 0, true),
|
|
hold: new EmitterOp('hold', 0, true),
|
|
lifespan: new EmitterOp('lifespan', 1000, true),
|
|
maxVelocityX: new EmitterOp('maxVelocityX', 10000),
|
|
maxVelocityY: new EmitterOp('maxVelocityY', 10000),
|
|
moveToX: new EmitterOp('moveToX', 0),
|
|
moveToY: new EmitterOp('moveToY', 0),
|
|
quantity: new EmitterOp('quantity', 1, true),
|
|
rotate: new EmitterOp('rotate', 0),
|
|
scaleX: new EmitterOp('scaleX', 1),
|
|
scaleY: new EmitterOp('scaleY', 1),
|
|
speedX: new EmitterOp('speedX', 0, true),
|
|
speedY: new EmitterOp('speedY', 0, true),
|
|
tint: new EmitterOp('tint', 0xffffff),
|
|
x: new EmitterOp('x', 0),
|
|
y: new EmitterOp('y', 0)
|
|
};
|
|
|
|
/**
|
|
* A radial emitter will emit particles in all directions between angle min and max,
|
|
* using {@link Phaser.GameObjects.Particles.ParticleEmitter#speed} as the value. If set to false then this acts as a point Emitter.
|
|
* A point emitter will emit particles only in the direction derived from the speedX and speedY values.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#radial
|
|
* @type {boolean}
|
|
* @default true
|
|
* @since 3.0.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setRadial
|
|
*/
|
|
this.radial = true;
|
|
|
|
/**
|
|
* Horizontal acceleration applied to emitted particles, in pixels per second squared.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#gravityX
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setGravity
|
|
*/
|
|
this.gravityX = 0;
|
|
|
|
/**
|
|
* Vertical acceleration applied to emitted particles, in pixels per second squared.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#gravityY
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setGravity
|
|
*/
|
|
this.gravityY = 0;
|
|
|
|
/**
|
|
* Whether accelerationX and accelerationY are non-zero. Set automatically during configuration.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#acceleration
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.0.0
|
|
*/
|
|
this.acceleration = false;
|
|
|
|
/**
|
|
* Whether moveToX and moveToY are set. Set automatically during configuration.
|
|
*
|
|
* When true the particles move toward the moveToX and moveToY coordinates and arrive at the end of their life.
|
|
* Emitter angle, speedX, and speedY are ignored.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#moveTo
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.0.0
|
|
*/
|
|
this.moveTo = false;
|
|
|
|
/**
|
|
* A function to call when a particle is emitted.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#emitCallback
|
|
* @type {?Phaser.Types.GameObjects.Particles.ParticleEmitterCallback}
|
|
* @default null
|
|
* @since 3.0.0
|
|
*/
|
|
this.emitCallback = null;
|
|
|
|
/**
|
|
* The calling context for {@link Phaser.GameObjects.Particles.ParticleEmitter#emitCallback}.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#emitCallbackScope
|
|
* @type {?*}
|
|
* @default null
|
|
* @since 3.0.0
|
|
*/
|
|
this.emitCallbackScope = null;
|
|
|
|
/**
|
|
* A function to call when a particle dies.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#deathCallback
|
|
* @type {?Phaser.Types.GameObjects.Particles.ParticleDeathCallback}
|
|
* @default null
|
|
* @since 3.0.0
|
|
*/
|
|
this.deathCallback = null;
|
|
|
|
/**
|
|
* The calling context for {@link Phaser.GameObjects.Particles.ParticleEmitter#deathCallback}.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#deathCallbackScope
|
|
* @type {?*}
|
|
* @default null
|
|
* @since 3.0.0
|
|
*/
|
|
this.deathCallbackScope = null;
|
|
|
|
/**
|
|
* Set to hard limit the amount of particle objects this emitter is allowed to create
|
|
* in total. This is the number of `Particle` instances it can create, not the number
|
|
* of 'alive' particles.
|
|
*
|
|
* 0 means unlimited.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#maxParticles
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.maxParticles = 0;
|
|
|
|
/**
|
|
* The maximum number of alive and rendering particles this emitter will update.
|
|
* When this limit is reached, a particle needs to die before another can be emitted.
|
|
*
|
|
* 0 means no limits.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#maxAliveParticles
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.60.0
|
|
*/
|
|
this.maxAliveParticles = 0;
|
|
|
|
/**
|
|
* If set, either via the Emitter config, or by directly setting this property,
|
|
* the Particle Emitter will stop emitting particles once this total has been
|
|
* reached. It will then enter a 'stopped' state, firing the `STOP`
|
|
* event. Note that entering a stopped state doesn't mean all the particles
|
|
* have finished, just that it's not emitting any further ones.
|
|
*
|
|
* To know when the final particle expires, listen for the COMPLETE event.
|
|
*
|
|
* Use this if you wish to launch an exact number of particles and then stop
|
|
* your emitter afterwards.
|
|
*
|
|
* The counter is reset each time the `ParticleEmitter.start` method is called.
|
|
*
|
|
* 0 means the emitter will not stop based on total emitted particles.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#stopAfter
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.60.0
|
|
*/
|
|
this.stopAfter = 0;
|
|
|
|
/**
|
|
* The number of milliseconds this emitter will emit particles for when in flow mode,
|
|
* before it stops emission. A value of 0 (the default) means there is no duration.
|
|
*
|
|
* When the duration expires the `STOP` event is emitted. Note that entering a
|
|
* stopped state doesn't mean all the particles have finished, just that it's
|
|
* not emitting any further ones.
|
|
*
|
|
* To know when the final particle expires, listen for the COMPLETE event.
|
|
*
|
|
* The counter is reset each time the `ParticleEmitter.start` method is called.
|
|
*
|
|
* 0 means the emitter will not stop based on duration.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#duration
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.60.0
|
|
*/
|
|
this.duration = 0;
|
|
|
|
/**
|
|
* For a flow emitter, the time interval (>= 0) between particle flow cycles in ms.
|
|
* A value of 0 means there is one particle flow cycle for each logic update (the maximum flow frequency). This is the default setting.
|
|
* For an exploding emitter, this value will be -1.
|
|
* Calling {@link Phaser.GameObjects.Particles.ParticleEmitter#flow} also puts the emitter in flow mode (frequency >= 0).
|
|
* Calling {@link Phaser.GameObjects.Particles.ParticleEmitter#explode} also puts the emitter in explode mode (frequency = -1).
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#frequency
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setFrequency
|
|
*/
|
|
this.frequency = 0;
|
|
|
|
/**
|
|
* Controls if the emitter is currently emitting a particle flow (when frequency >= 0).
|
|
*
|
|
* Already alive particles will continue to update until they expire.
|
|
*
|
|
* Controlled by {@link Phaser.GameObjects.Particles.ParticleEmitter#start} and {@link Phaser.GameObjects.Particles.ParticleEmitter#stop}.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#emitting
|
|
* @type {boolean}
|
|
* @default true
|
|
* @since 3.0.0
|
|
*/
|
|
this.emitting = true;
|
|
|
|
/**
|
|
* Newly emitted particles are added to the top of the particle list, i.e. rendered above those already alive.
|
|
*
|
|
* Set to false to send them to the back.
|
|
*
|
|
* Also see the `sortOrder` property for more complex particle sorting.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleBringToTop
|
|
* @type {boolean}
|
|
* @default true
|
|
* @since 3.0.0
|
|
*/
|
|
this.particleBringToTop = true;
|
|
|
|
/**
|
|
* The time rate applied to active particles, affecting lifespan, movement, and tweens. Values larger than 1 are faster than normal.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#timeScale
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
this.timeScale = 1;
|
|
|
|
/**
|
|
* An array containing Particle Emission Zones. These can be either EdgeZones or RandomZones.
|
|
*
|
|
* Particles are emitted from a randomly selected zone from this array.
|
|
*
|
|
* Prior to Phaser v3.60 an Emitter could only have one single Emission Zone.
|
|
* In 3.60 they can now have an array of Emission Zones.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#emitZones
|
|
* @type {Phaser.GameObjects.Particles.Zones.EdgeZone[]|Phaser.GameObjects.Particles.Zones.RandomZone[]}
|
|
* @since 3.60.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setEmitZone
|
|
*/
|
|
this.emitZones = [];
|
|
|
|
/**
|
|
* An array containing Particle Death Zone objects. A particle is immediately killed as soon as its x/y coordinates
|
|
* intersect with any of the configured Death Zones.
|
|
*
|
|
* Prior to Phaser v3.60 an Emitter could only have one single Death Zone.
|
|
* In 3.60 they can now have an array of Death Zones.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#deathZones
|
|
* @type {Phaser.GameObjects.Particles.Zones.DeathZone[]}
|
|
* @since 3.60.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setDeathZone
|
|
*/
|
|
this.deathZones = [];
|
|
|
|
/**
|
|
* An optional Rectangle object that is used during rendering to cull Particles from
|
|
* display. For example, if your particles are limited to only move within a 300x300
|
|
* sized area from their origin, then you can set this Rectangle to those dimensions.
|
|
*
|
|
* The renderer will check to see if the `viewBounds` Rectangle intersects with the
|
|
* Camera bounds during the render step and if not it will skip rendering the Emitter
|
|
* entirely.
|
|
*
|
|
* This allows you to create many emitters in a Scene without the cost of
|
|
* rendering if the contents aren't visible.
|
|
*
|
|
* Note that the Emitter will not perform any checks to see if the Particles themselves
|
|
* are outside of these bounds, or not. It will simply check the bounds against the
|
|
* camera. Use the `getBounds` method with the `advance` parameter to help define
|
|
* the location and placement of the view bounds.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#viewBounds
|
|
* @type {?Phaser.Geom.Rectangle}
|
|
* @default null
|
|
* @since 3.60.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setViewBounds
|
|
*/
|
|
this.viewBounds = null;
|
|
|
|
/**
|
|
* A Game Object whose position is used as the particle origin.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#follow
|
|
* @type {?Phaser.GameObjects.GameObject}
|
|
* @default null
|
|
* @since 3.0.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#startFollow
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#stopFollow
|
|
*/
|
|
this.follow = null;
|
|
|
|
/**
|
|
* The offset of the particle origin from the {@link Phaser.GameObjects.Particles.ParticleEmitter#follow} target.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#followOffset
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.0.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#startFollow
|
|
*/
|
|
this.followOffset = new Vector2();
|
|
|
|
/**
|
|
* Whether the emitter's {@link Phaser.GameObjects.Particles.ParticleEmitter#visible} state will track
|
|
* the {@link Phaser.GameObjects.Particles.ParticleEmitter#follow} target's visibility state.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#trackVisible
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.0.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#startFollow
|
|
*/
|
|
this.trackVisible = false;
|
|
|
|
/**
|
|
* The texture frames assigned to particles.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#frames
|
|
* @type {Phaser.Textures.Frame[]}
|
|
* @since 3.0.0
|
|
*/
|
|
this.frames = [];
|
|
|
|
/**
|
|
* Whether texture {@link Phaser.GameObjects.Particles.ParticleEmitter#frames} are selected at random.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#randomFrame
|
|
* @type {boolean}
|
|
* @default true
|
|
* @since 3.0.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setEmitterFrame
|
|
*/
|
|
this.randomFrame = true;
|
|
|
|
/**
|
|
* The number of consecutive particles that receive a single texture frame (per frame cycle).
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#frameQuantity
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.0.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setEmitterFrame
|
|
*/
|
|
this.frameQuantity = 1;
|
|
|
|
/**
|
|
* The animations assigned to particles.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#anims
|
|
* @type {string[]}
|
|
* @since 3.60.0
|
|
*/
|
|
this.anims = [];
|
|
|
|
/**
|
|
* Whether animations {@link Phaser.GameObjects.Particles.ParticleEmitter#anims} are selected at random.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#randomAnim
|
|
* @type {boolean}
|
|
* @default true
|
|
* @since 3.60.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setAnim
|
|
*/
|
|
this.randomAnim = true;
|
|
|
|
/**
|
|
* The number of consecutive particles that receive a single animation (per frame cycle).
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#animQuantity
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.60.0
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setAnim
|
|
*/
|
|
this.animQuantity = 1;
|
|
|
|
/**
|
|
* An array containing all currently inactive Particle instances.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#dead
|
|
* @type {Phaser.GameObjects.Particles.Particle[]}
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
this.dead = [];
|
|
|
|
/**
|
|
* An array containing all currently live and rendering Particle instances.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#alive
|
|
* @type {Phaser.GameObjects.Particles.Particle[]}
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
this.alive = [];
|
|
|
|
/**
|
|
* Internal array that holds counter data:
|
|
*
|
|
* 0 - flowCounter - The time until next flow cycle.
|
|
* 1 - frameCounter - Counts up to {@link Phaser.GameObjects.Particles.ParticleEmitter#frameQuantity}.
|
|
* 2 - animCounter - Counts up to animQuantity.
|
|
* 3 - elapsed - The time remaining until the `duration` limit is reached.
|
|
* 4 - stopCounter - The number of particles remaining until `stopAfter` limit is reached.
|
|
* 5 - completeFlag - Has the COMPLETE event been emitted?
|
|
* 6 - zoneIndex - The emit zone index counter.
|
|
* 7 - zoneTotal - The emit zone total counter.
|
|
* 8 - currentFrame - The current texture frame, as an index of {@link Phaser.GameObjects.Particles.ParticleEmitter#frames}.
|
|
* 9 - currentAnim - The current animation, as an index of {@link Phaser.GameObjects.Particles.ParticleEmitter#anims}.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#counters
|
|
* @type {Float32Array}
|
|
* @private
|
|
* @since 3.60.0
|
|
*/
|
|
this.counters = new Float32Array(10);
|
|
|
|
/**
|
|
* An internal property used to tell when the emitter is in fast-forwarc mode.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#skipping
|
|
* @type {boolean}
|
|
* @default true
|
|
* @since 3.60.0
|
|
*/
|
|
this.skipping = false;
|
|
|
|
/**
|
|
* An internal Transform Matrix used to cache this emitters world matrix.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#worldMatrix
|
|
* @type {Phaser.GameObjects.Components.TransformMatrix}
|
|
* @since 3.60.0
|
|
*/
|
|
this.worldMatrix = new TransformMatrix();
|
|
|
|
/**
|
|
* Optionally sort the particles before they render based on this
|
|
* property. The property must exist on the `Particle` class, such
|
|
* as `y`, `lifeT`, `scaleX`, etc.
|
|
*
|
|
* When set this overrides the `particleBringToTop` setting.
|
|
*
|
|
* To reset this and disable sorting, so this property to an empty string.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#sortProperty
|
|
* @type {string}
|
|
* @since 3.60.0
|
|
*/
|
|
this.sortProperty = '';
|
|
|
|
/**
|
|
* When `sortProperty` is defined this controls the sorting order,
|
|
* either ascending or descending. Toggle to control the visual effect.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#sortOrderAsc
|
|
* @type {boolean}
|
|
* @since 3.60.0
|
|
*/
|
|
this.sortOrderAsc = true;
|
|
|
|
/**
|
|
* The callback used to sort the particles. Only used if `sortProperty`
|
|
* has been set. Set this via the `setSortCallback` method.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#sortCallback
|
|
* @type {?Phaser.Types.GameObjects.Particles.ParticleSortCallback}
|
|
* @since 3.60.0
|
|
*/
|
|
this.sortCallback = this.depthSortCallback;
|
|
|
|
/**
|
|
* A list of Particle Processors being managed by this Emitter.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#processors
|
|
* @type {Phaser.Structs.List.<Phaser.GameObjects.Particles.ParticleProcessor>}
|
|
* @since 3.60.0
|
|
*/
|
|
this.processors = new List(this);
|
|
|
|
/**
|
|
* The tint fill mode used by the Particles in this Emitter.
|
|
*
|
|
* `false` = An additive tint (the default), where vertices colors are blended with the texture.
|
|
* `true` = A fill tint, where the vertices colors replace the texture, but respects texture alpha.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#tintFill
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.60.0
|
|
*/
|
|
this.tintFill = false;
|
|
|
|
this.initPipeline();
|
|
this.initPostPipeline();
|
|
|
|
this.setPosition(x, y);
|
|
this.setTexture(texture);
|
|
|
|
if (config)
|
|
{
|
|
this.setConfig(config);
|
|
}
|
|
},
|
|
|
|
// Overrides Game Object method
|
|
addedToScene: function ()
|
|
{
|
|
this.scene.sys.updateList.add(this);
|
|
},
|
|
|
|
// Overrides Game Object method
|
|
removedFromScene: function ()
|
|
{
|
|
this.scene.sys.updateList.remove(this);
|
|
},
|
|
|
|
/**
|
|
* Takes an Emitter Configuration file and resets this Emitter, using any
|
|
* properties defined in the config to then set it up again.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setConfig
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.ParticleEmitterConfig} config - Settings for this emitter.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setConfig: function (config)
|
|
{
|
|
if (!config)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
var i = 0;
|
|
var key = '';
|
|
|
|
var ops = this.ops;
|
|
|
|
for (i = 0; i < configOpMap.length; i++)
|
|
{
|
|
key = configOpMap[i];
|
|
|
|
ops[key].loadConfig(config);
|
|
}
|
|
|
|
for (i = 0; i < configFastMap.length; i++)
|
|
{
|
|
key = configFastMap[i];
|
|
|
|
// Only update properties from their current state if they exist in the given config
|
|
if (HasValue(config, key))
|
|
{
|
|
this[key] = GetFastValue(config, key);
|
|
}
|
|
}
|
|
|
|
this.acceleration = (this.accelerationX !== 0 || this.accelerationY !== 0);
|
|
|
|
this.moveTo = (this.moveToX !== 0 && this.moveToY !== 0);
|
|
|
|
// Special 'speed' override
|
|
|
|
if (HasValue(config, 'speed'))
|
|
{
|
|
ops.speedX.loadConfig(config, 'speed');
|
|
ops.speedY.active = false;
|
|
}
|
|
|
|
// If you specify speedX, speedY or moveTo then it changes the emitter from radial to a point emitter
|
|
if (HasAny(config, [ 'speedX', 'speedY' ]) || this.moveTo)
|
|
{
|
|
this.radial = false;
|
|
}
|
|
|
|
// Special 'scale' override
|
|
|
|
if (HasValue(config, 'scale'))
|
|
{
|
|
ops.scaleX.loadConfig(config, 'scale');
|
|
ops.scaleY.active = false;
|
|
}
|
|
|
|
if (HasValue(config, 'callbackScope'))
|
|
{
|
|
var callbackScope = GetFastValue(config, 'callbackScope', null);
|
|
|
|
this.emitCallbackScope = callbackScope;
|
|
this.deathCallbackScope = callbackScope;
|
|
}
|
|
|
|
if (HasValue(config, 'emitZone'))
|
|
{
|
|
this.addEmitZone(config.emitZone);
|
|
}
|
|
|
|
if (HasValue(config, 'deathZone'))
|
|
{
|
|
this.addDeathZone(config.deathZone);
|
|
}
|
|
|
|
if (HasValue(config, 'bounds'))
|
|
{
|
|
var bounds = this.addParticleBounds(config.bounds);
|
|
|
|
bounds.collideLeft = GetFastValue(config, 'collideLeft', true);
|
|
bounds.collideRight = GetFastValue(config, 'collideRight', true);
|
|
bounds.collideTop = GetFastValue(config, 'collideTop', true);
|
|
bounds.collideBottom = GetFastValue(config, 'collideBottom', true);
|
|
}
|
|
|
|
if (HasValue(config, 'followOffset'))
|
|
{
|
|
this.followOffset.setFromObject(GetFastValue(config, 'followOffset', 0));
|
|
}
|
|
|
|
if (HasValue(config, 'texture'))
|
|
{
|
|
this.setTexture(config.texture);
|
|
}
|
|
|
|
if (HasValue(config, 'frame'))
|
|
{
|
|
this.setEmitterFrame(config.frame);
|
|
}
|
|
else if (HasValue(config, 'anim'))
|
|
{
|
|
this.setAnim(config.anim);
|
|
}
|
|
|
|
if (HasValue(config, 'reserve'))
|
|
{
|
|
this.reserve(config.reserve);
|
|
}
|
|
|
|
if (HasValue(config, 'advance'))
|
|
{
|
|
this.fastForward(config.advance);
|
|
}
|
|
|
|
this.resetCounters(this.frequency, this.emitting);
|
|
|
|
if (this.emitting)
|
|
{
|
|
this.emit(Events.START, this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Creates a description of this emitter suitable for JSON serialization.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#toJSON
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Types.GameObjects.JSONGameObject} A JSON representation of the Game Object.
|
|
*/
|
|
toJSON: function ()
|
|
{
|
|
var output = ComponentsToJSON(this);
|
|
|
|
var i = 0;
|
|
var key = '';
|
|
|
|
for (i = 0; i < configFastMap.length; i++)
|
|
{
|
|
key = configFastMap[i];
|
|
|
|
output[key] = this[key];
|
|
}
|
|
|
|
var ops = this.ops;
|
|
|
|
for (i = 0; i < configOpMap.length; i++)
|
|
{
|
|
key = configOpMap[i];
|
|
|
|
if (ops[key])
|
|
{
|
|
output[key] = ops[key].toJSON();
|
|
}
|
|
}
|
|
|
|
// special handlers
|
|
if (!ops.speedY.active)
|
|
{
|
|
delete output.speedX;
|
|
output.speed = ops.speedX.toJSON();
|
|
}
|
|
|
|
if (this.scaleX === this.scaleY)
|
|
{
|
|
delete output.scaleX;
|
|
delete output.scaleY;
|
|
output.scale = ops.scaleX.toJSON();
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Resets the internal counter trackers.
|
|
*
|
|
* You shouldn't ever need to call this directly.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#resetCounters
|
|
* @since 3.60.0
|
|
*
|
|
* @param {number} frequency - The frequency counter.
|
|
* @param {boolean} on - Set the complete flag.
|
|
*/
|
|
resetCounters: function (frequency, on)
|
|
{
|
|
var counters = this.counters;
|
|
|
|
counters.fill(0);
|
|
|
|
counters[0] = frequency;
|
|
|
|
if (on)
|
|
{
|
|
counters[5] = 1;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Continuously moves the particle origin to follow a Game Object's position.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#startFollow
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} target - The Game Object to follow.
|
|
* @param {number} [offsetX=0] - Horizontal offset of the particle origin from the Game Object.
|
|
* @param {number} [offsetY=0] - Vertical offset of the particle origin from the Game Object.
|
|
* @param {boolean} [trackVisible=false] - Whether the emitter's visible state will track the target's visible state.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
startFollow: function (target, offsetX, offsetY, trackVisible)
|
|
{
|
|
if (offsetX === undefined) { offsetX = 0; }
|
|
if (offsetY === undefined) { offsetY = 0; }
|
|
if (trackVisible === undefined) { trackVisible = false; }
|
|
|
|
this.follow = target;
|
|
this.followOffset.set(offsetX, offsetY);
|
|
this.trackVisible = trackVisible;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Stops following a Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#stopFollow
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
stopFollow: function ()
|
|
{
|
|
this.follow = null;
|
|
this.followOffset.set(0, 0);
|
|
this.trackVisible = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Chooses a texture frame from {@link Phaser.GameObjects.Particles.ParticleEmitter#frames}.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#getFrame
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Textures.Frame} The texture frame.
|
|
*/
|
|
getFrame: function ()
|
|
{
|
|
var frames = this.frames;
|
|
var len = frames.length;
|
|
var current;
|
|
|
|
if (len === 1)
|
|
{
|
|
current = frames[0];
|
|
}
|
|
else if (this.randomFrame)
|
|
{
|
|
current = GetRandom(frames);
|
|
}
|
|
else
|
|
{
|
|
current = frames[this.currentFrame];
|
|
|
|
this.frameCounter++;
|
|
|
|
if (this.frameCounter === this.frameQuantity)
|
|
{
|
|
this.frameCounter = 0;
|
|
|
|
this.currentFrame++;
|
|
|
|
if (this.currentFrame === len)
|
|
{
|
|
this.currentFrame = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return this.texture.get(current);
|
|
},
|
|
|
|
/**
|
|
* Sets a pattern for assigning texture frames to emitted particles. The `frames` configuration can be any of:
|
|
*
|
|
* frame: 0
|
|
* frame: 'red'
|
|
* frame: [ 0, 1, 2, 3 ]
|
|
* frame: [ 'red', 'green', 'blue', 'pink', 'white' ]
|
|
* frame: { frames: [ 'red', 'green', 'blue', 'pink', 'white' ], [cycle: bool], [quantity: int] }
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setEmitterFrame
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(array|string|number|Phaser.Types.GameObjects.Particles.ParticleEmitterFrameConfig)} frames - One or more texture frames, or a configuration object.
|
|
* @param {boolean} [pickRandom=true] - Whether frames should be assigned at random from `frames`.
|
|
* @param {number} [quantity=1] - The number of consecutive particles that will receive each frame.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setEmitterFrame: function (frames, pickRandom, quantity)
|
|
{
|
|
if (pickRandom === undefined) { pickRandom = true; }
|
|
if (quantity === undefined) { quantity = 1; }
|
|
|
|
this.randomFrame = pickRandom;
|
|
this.frameQuantity = quantity;
|
|
|
|
this.currentFrame = 0;
|
|
|
|
var t = typeof (frames);
|
|
|
|
this.frames.length = 0;
|
|
|
|
if (Array.isArray(frames))
|
|
{
|
|
this.frames = this.frames.concat(frames);
|
|
}
|
|
else if (t === 'string' || t === 'number')
|
|
{
|
|
this.frames.push(frames);
|
|
}
|
|
else if (t === 'object')
|
|
{
|
|
var frameConfig = frames;
|
|
|
|
frames = GetFastValue(frameConfig, 'frames', null);
|
|
|
|
if (frames)
|
|
{
|
|
this.frames = this.frames.concat(frames);
|
|
}
|
|
|
|
var isCycle = GetFastValue(frameConfig, 'cycle', false);
|
|
|
|
this.randomFrame = (isCycle) ? false : true;
|
|
|
|
this.frameQuantity = GetFastValue(frameConfig, 'quantity', quantity);
|
|
}
|
|
|
|
if (this.frames.length === 1)
|
|
{
|
|
this.frameQuantity = 1;
|
|
this.randomFrame = false;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Chooses an animation from {@link Phaser.GameObjects.Particles.ParticleEmitter#anims}, if populated.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#getAnim
|
|
* @since 3.60.0
|
|
*
|
|
* @return {string} The animation to play, or `null` if there aren't any.
|
|
*/
|
|
getAnim: function ()
|
|
{
|
|
var anims = this.anims;
|
|
var len = anims.length;
|
|
|
|
if (len === 0)
|
|
{
|
|
return null;
|
|
}
|
|
else if (len === 1)
|
|
{
|
|
return anims[0];
|
|
}
|
|
else if (this.randomAnim)
|
|
{
|
|
return GetRandom(anims);
|
|
}
|
|
else
|
|
{
|
|
var anim = anims[this.currentAnim];
|
|
|
|
this.animCounter++;
|
|
|
|
if (this.animCounter >= this.animQuantity)
|
|
{
|
|
this.animCounter = 0;
|
|
this.currentAnim = Wrap(this.currentAnim + 1, 0, len - 1);
|
|
}
|
|
|
|
return anim;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Sets a pattern for assigning animations to emitted particles. The `anims` configuration can be any of:
|
|
*
|
|
* anim: 'red'
|
|
* anim: [ 'red', 'green', 'blue', 'pink', 'white' ]
|
|
* anim: { anims: [ 'red', 'green', 'blue', 'pink', 'white' ], [cycle: bool], [quantity: int] }
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setAnim
|
|
* @since 3.60.0
|
|
*
|
|
* @param {(string|string[]|Phaser.Types.GameObjects.Particles.ParticleEmitterAnimConfig)} anims - One or more animations, or a configuration object.
|
|
* @param {boolean} [pickRandom=true] - Whether animations should be assigned at random from `anims`.
|
|
* @param {number} [quantity=1] - The number of consecutive particles that will receive each animation.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setAnim: function (anims, pickRandom, quantity)
|
|
{
|
|
if (pickRandom === undefined) { pickRandom = true; }
|
|
if (quantity === undefined) { quantity = 1; }
|
|
|
|
this.randomAnim = pickRandom;
|
|
this.animQuantity = quantity;
|
|
|
|
this.currentAnim = 0;
|
|
|
|
var t = typeof (anims);
|
|
|
|
this.anims.length = 0;
|
|
|
|
if (Array.isArray(anims))
|
|
{
|
|
this.anims = this.anims.concat(anims);
|
|
}
|
|
else if (t === 'string')
|
|
{
|
|
this.anims.push(anims);
|
|
}
|
|
else if (t === 'object')
|
|
{
|
|
var animConfig = anims;
|
|
|
|
anims = GetFastValue(animConfig, 'anims', null);
|
|
|
|
if (anims)
|
|
{
|
|
this.anims = this.anims.concat(anims);
|
|
}
|
|
|
|
var isCycle = GetFastValue(animConfig, 'cycle', false);
|
|
|
|
this.randomAnim = (isCycle) ? false : true;
|
|
|
|
this.animQuantity = GetFastValue(animConfig, 'quantity', quantity);
|
|
}
|
|
|
|
if (this.anims.length === 1)
|
|
{
|
|
this.animQuantity = 1;
|
|
this.randomAnim = false;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Turns {@link Phaser.GameObjects.Particles.ParticleEmitter#radial} particle movement on or off.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setRadial
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} [value=true] - Radial mode (true) or point mode (true).
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setRadial: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.radial = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Creates a Particle Bounds processor and adds it to this Emitter.
|
|
*
|
|
* This processor will check to see if any of the active Particles hit
|
|
* the defined boundary, as specified by a Rectangle shape in world-space.
|
|
*
|
|
* If so, they are 'rebounded' back again by having their velocity adjusted.
|
|
*
|
|
* The strength of the rebound is controlled by the `Particle.bounce`
|
|
* property.
|
|
*
|
|
* You should be careful to ensure that you emit particles within a bounds,
|
|
* if set, otherwise it will lead to unpredictable visual results as the
|
|
* particles are hastily repositioned.
|
|
*
|
|
* The Particle Bounds processor is returned from this method. If you wish
|
|
* to modify the area you can directly change its `bounds` property, along
|
|
* with the `collideLeft` etc values.
|
|
*
|
|
* To disable the bounds you can either set its `active` property to `false`,
|
|
* or if you no longer require it, call `ParticleEmitter.removeParticleProcessor`.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#addParticleBounds
|
|
* @since 3.60.0
|
|
*
|
|
* @param {(number|Phaser.Types.GameObjects.Particles.ParticleEmitterBounds|Phaser.Types.GameObjects.Particles.ParticleEmitterBoundsAlt)} x - The x-coordinate of the left edge of the boundary, or an object representing a rectangle.
|
|
* @param {number} [y] - The y-coordinate of the top edge of the boundary.
|
|
* @param {number} [width] - The width of the boundary.
|
|
* @param {number} [height] - The height of the boundary.
|
|
* @param {boolean} [collideLeft=true] - Whether particles interact with the left edge of the bounds.
|
|
* @param {boolean} [collideRight=true] - Whether particles interact with the right edge of the bounds.
|
|
* @param {boolean} [collideTop=true] - Whether particles interact with the top edge of the bounds.
|
|
* @param {boolean} [collideBottom=true] - Whether particles interact with the bottom edge of the bounds.
|
|
*
|
|
* @return {Phaser.GameObjects.Particles.ParticleBounds} The Particle Bounds processor.
|
|
*/
|
|
addParticleBounds: function (x, y, width, height, collideLeft, collideRight, collideTop, collideBottom)
|
|
{
|
|
if (typeof x === 'object')
|
|
{
|
|
var obj = x;
|
|
|
|
x = obj.x;
|
|
y = obj.y;
|
|
width = (HasValue(obj, 'w')) ? obj.w : obj.width;
|
|
height = (HasValue(obj, 'h')) ? obj.h : obj.height;
|
|
}
|
|
|
|
return this.addParticleProcessor(new ParticleBounds(x, y, width, height, collideLeft, collideRight, collideTop, collideBottom));
|
|
},
|
|
|
|
/**
|
|
* Sets the initial radial speed of emitted particles.
|
|
*
|
|
* Changes the emitter to radial mode.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleSpeed
|
|
* @since 3.60.0
|
|
*
|
|
* @param {number} x - The horizontal speed of the emitted Particles.
|
|
* @param {number} [y=x] - The vertical speed of emitted Particles. If not set it will use the `x` value.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setParticleSpeed: function (x, y)
|
|
{
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.ops.speedX.onChange(x);
|
|
|
|
if (x === y)
|
|
{
|
|
this.ops.speedY.active = false;
|
|
}
|
|
else
|
|
{
|
|
this.ops.speedY.onChange(y);
|
|
}
|
|
|
|
// If you specify speedX and Y then it changes the emitter from radial to a point emitter
|
|
this.radial = true;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the vertical and horizontal scale of the emitted particles.
|
|
*
|
|
* You can also set the scale of the entire emitter via `setScale`.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleScale
|
|
* @since 3.60.0
|
|
*
|
|
* @param {number} [x=1] - The horizontal scale of the emitted Particles.
|
|
* @param {number} [y=x] - The vertical scale of emitted Particles. If not set it will use the `x` value.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setParticleScale: function (x, y)
|
|
{
|
|
if (x === undefined) { x = 1; }
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.ops.scaleX.onChange(x);
|
|
this.ops.scaleY.onChange(y);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the gravity applied to emitted particles.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleGravity
|
|
* @since 3.60.0
|
|
*
|
|
* @param {number} x - Horizontal acceleration due to gravity, in pixels per second squared. Set to zero for no gravity.
|
|
* @param {number} y - Vertical acceleration due to gravity, in pixels per second squared. Set to zero for no gravity.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setParticleGravity: function (x, y)
|
|
{
|
|
this.gravityX = x;
|
|
this.gravityY = y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the opacity (alpha) of emitted particles.
|
|
*
|
|
* You can also set the alpha of the entire emitter via `setAlpha`.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleAlpha
|
|
* @since 3.60.0
|
|
*
|
|
* @param {(Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType)} value - A value between 0 (transparent) and 1 (opaque).
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setParticleAlpha: function (value)
|
|
{
|
|
this.ops.alpha.onChange(value);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the color tint of emitted particles.
|
|
*
|
|
* This is a WebGL only feature.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleTint
|
|
* @since 3.60.0
|
|
* @webglOnly
|
|
*
|
|
* @param {(Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType)} value - A value between 0 and 0xffffff.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setParticleTint: function (value)
|
|
{
|
|
this.ops.tint.onChange(value);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the angle of a {@link Phaser.GameObjects.Particles.ParticleEmitter#radial} particle stream.
|
|
*
|
|
* The value is given in degrees using Phaser's right-handed coordinate system.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setEmitterAngle
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} value - The angle of the initial velocity of emitted particles, in degrees.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setEmitterAngle: function (value)
|
|
{
|
|
this.ops.angle.onChange(value);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the lifespan of newly emitted particles in milliseconds.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleLifespan
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} value - The lifespan of a particle, in ms.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setParticleLifespan: function (value)
|
|
{
|
|
this.ops.lifespan.onChange(value);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the number of particles released at each flow cycle or explosion.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setQuantity
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} quantity - The number of particles to release at each flow cycle or explosion.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setQuantity: function (quantity)
|
|
{
|
|
this.quantity = quantity;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the emitter's {@link Phaser.GameObjects.Particles.ParticleEmitter#frequency}
|
|
* and {@link Phaser.GameObjects.Particles.ParticleEmitter#quantity}.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setFrequency
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} frequency - The time interval (>= 0) of each flow cycle, in ms; or -1 to put the emitter in explosion mode.
|
|
* @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} [quantity] - The number of particles to release at each flow cycle or explosion.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setFrequency: function (frequency, quantity)
|
|
{
|
|
this.frequency = frequency;
|
|
|
|
this.flowCounter = (frequency > 0) ? frequency : 0;
|
|
|
|
if (quantity)
|
|
{
|
|
this.quantity = quantity;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Adds a new Particle Death Zone to this Emitter.
|
|
*
|
|
* A particle is immediately killed as soon as its x/y coordinates intersect
|
|
* with any of the configured Death Zones.
|
|
*
|
|
* The `source` can be a Geometry Shape, such as a Circle, Rectangle or Triangle.
|
|
* Any valid object from the `Phaser.Geometry` namespace is allowed, as long as
|
|
* it supports a `contains` function. You can set the `type` to be either `onEnter`
|
|
* or `onLeave`.
|
|
*
|
|
* A single Death Zone instance can only exist once within this Emitter, but can belong
|
|
* to multiple Emitters.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#addDeathZone
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.DeathZoneObject|Phaser.Types.GameObjects.Particles.DeathZoneObject[]} config - A Death Zone configuration object, a Death Zone instance, a valid Geometry object or an array of them.
|
|
*
|
|
* @return {Phaser.GameObjects.Particles.Zones.DeathZone} The Death Zone that was added to this Emitter.
|
|
*/
|
|
addDeathZone: function (config)
|
|
{
|
|
if (!Array.isArray(config))
|
|
{
|
|
config = [ config ];
|
|
}
|
|
|
|
var zone;
|
|
var deathZones = this.deathZones;
|
|
|
|
for (var i = 0; i < config.length; i++)
|
|
{
|
|
zone = config[i];
|
|
|
|
if (zone instanceof DeathZone)
|
|
{
|
|
deathZones.push(zone);
|
|
}
|
|
else if (typeof zone.contains === 'function')
|
|
{
|
|
zone = new DeathZone(zone, true);
|
|
|
|
deathZones.push(zone);
|
|
}
|
|
else
|
|
{
|
|
var type = GetFastValue(zone, 'type', 'onEnter');
|
|
var source = GetFastValue(zone, 'source', null);
|
|
|
|
if (source && typeof source.contains === 'function')
|
|
{
|
|
var killOnEnter = (type === 'onEnter') ? true : false;
|
|
|
|
zone = new DeathZone(source, killOnEnter);
|
|
|
|
deathZones.push(zone);
|
|
}
|
|
}
|
|
}
|
|
|
|
return zone;
|
|
},
|
|
|
|
/**
|
|
* Removes the given Particle Death Zone from this Emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#removeDeathZone
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.GameObjects.Particles.Zones.DeathZone} zone - The Death Zone that should be removed from this Emitter.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
removeDeathZone: function (zone)
|
|
{
|
|
Remove(this.deathZones, zone);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Clear all Death Zones from this Particle Emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#clearDeathZones
|
|
* @since 3.61.0
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
clearDeathZones: function ()
|
|
{
|
|
this.deathZones.length = 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Adds a new Particle Emission Zone to this Emitter.
|
|
*
|
|
* An {@link Phaser.Types.GameObjects.Particles.ParticleEmitterEdgeZoneConfig EdgeZone} places particles on its edges.
|
|
* Its {@link Phaser.Types.GameObjects.Particles.EdgeZoneSource source} can be a Curve, Path, Circle, Ellipse, Line, Polygon, Rectangle, or Triangle;
|
|
* or any object with a suitable {@link Phaser.Types.GameObjects.Particles.EdgeZoneSourceCallback getPoints} method.
|
|
*
|
|
* A {@link Phaser.Types.GameObjects.Particles.ParticleEmitterRandomZoneConfig RandomZone} places the particles randomly within its interior.
|
|
* Its {@link RandomZoneSource source} can be a Circle, Ellipse, Line, Polygon, Rectangle, or Triangle; or any object with a suitable {@link Phaser.Types.GameObjects.Particles.RandomZoneSourceCallback getRandomPoint} method.
|
|
*
|
|
* An Emission Zone can only exist once within this Emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#addEmitZone
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.EmitZoneObject|Phaser.Types.GameObjects.Particles.EmitZoneObject[]} zone - An Emission Zone configuration object, a RandomZone or EdgeZone instance, or an array of them.
|
|
*
|
|
* @return {Phaser.GameObjects.Particles.Zones.EdgeZone[]|Phaser.GameObjects.Particles.Zones.RandomZone[]} An array of the Emission Zones that were added to this Emitter.
|
|
*/
|
|
addEmitZone: function (config)
|
|
{
|
|
if (!Array.isArray(config))
|
|
{
|
|
config = [ config ];
|
|
}
|
|
|
|
var zone;
|
|
var emitZones = this.emitZones;
|
|
var output = [];
|
|
|
|
for (var i = 0; i < config.length; i++)
|
|
{
|
|
zone = config[i];
|
|
|
|
if (zone instanceof RandomZone || zone instanceof EdgeZone)
|
|
{
|
|
emitZones.push(zone);
|
|
}
|
|
else
|
|
{
|
|
// Where source = Geom like Circle, or a Path or Curve
|
|
// emitZone: { type: 'random', source: X }
|
|
// emitZone: { type: 'edge', source: X, quantity: 32, [stepRate=0], [yoyo=false], [seamless=true], [total=1] }
|
|
|
|
var type = GetFastValue(zone, 'type', 'random');
|
|
var source = GetFastValue(zone, 'source', null);
|
|
|
|
if (type === 'random')
|
|
{
|
|
zone = new RandomZone(source);
|
|
}
|
|
else if (type === 'edge')
|
|
{
|
|
var quantity = GetFastValue(zone, 'quantity', 1);
|
|
var stepRate = GetFastValue(zone, 'stepRate', 0);
|
|
var yoyo = GetFastValue(zone, 'yoyo', false);
|
|
var seamless = GetFastValue(zone, 'seamless', true);
|
|
var total = GetFastValue(zone, 'total', -1);
|
|
|
|
zone = new EdgeZone(source, quantity, stepRate, yoyo, seamless, total);
|
|
}
|
|
|
|
if (zone)
|
|
{
|
|
emitZones.push(zone);
|
|
}
|
|
}
|
|
|
|
output.push(zone);
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Removes the given Particle Emission Zone from this Emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#removeEmitZone
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.GameObjects.Particles.Zones.EdgeZone|Phaser.GameObjects.Particles.Zones.RandomZone} zone - The Emission Zone that should be removed from this Emitter.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
removeEmitZone: function (zone)
|
|
{
|
|
Remove(this.emitZones, zone);
|
|
|
|
this.zoneIndex = 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Clear all Emission Zones from this Particle Emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#clearEmitZones
|
|
* @since 3.61.0
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
clearEmitZones: function ()
|
|
{
|
|
this.emitZones.length = 0;
|
|
|
|
this.zoneIndex = 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Takes the given particle and sets its x/y coordinates to match the next available
|
|
* emission zone, if any have been configured. This method is called automatically
|
|
* as part of the `Particle.fire` process.
|
|
*
|
|
* The Emit Zones are iterated in sequence. Once a zone has had a particle emitted
|
|
* from it, then the next zone is used and so on, in a loop.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#getEmitZone
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.GameObjects.Particles.Particle} particle - The particle to set the emission zone for.
|
|
*/
|
|
getEmitZone: function (particle)
|
|
{
|
|
var zones = this.emitZones;
|
|
var len = zones.length;
|
|
|
|
if (len === 0)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
var zone = zones[this.zoneIndex];
|
|
|
|
zone.getPoint(particle);
|
|
|
|
if (zone.total > -1)
|
|
{
|
|
this.zoneTotal++;
|
|
|
|
if (this.zoneTotal === zone.total)
|
|
{
|
|
this.zoneTotal = 0;
|
|
|
|
this.zoneIndex++;
|
|
|
|
if (this.zoneIndex === len)
|
|
{
|
|
this.zoneIndex = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Takes the given particle and checks to see if any of the configured Death Zones
|
|
* will kill it and returns the result. This method is called automatically as part
|
|
* of the `Particle.update` process.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#getDeathZone
|
|
* @fires Phaser.GameObjects.Particles.Events#DEATH_ZONE
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.GameObjects.Particles.Particle} particle - The particle to test against the Death Zones.
|
|
*
|
|
* @return {boolean} `true` if the particle should be killed, otherwise `false`.
|
|
*/
|
|
getDeathZone: function (particle)
|
|
{
|
|
var zones = this.deathZones;
|
|
|
|
for (var i = 0; i < zones.length; i++)
|
|
{
|
|
var zone = zones[i];
|
|
|
|
if (zone.willKill(particle))
|
|
{
|
|
this.emit(Events.DEATH_ZONE, this, particle, zone);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Changes the currently active Emission Zone. The zones should have already
|
|
* been added to this Emitter either via the emitter config, or the
|
|
* `addEmitZone` method.
|
|
*
|
|
* Call this method by passing either a numeric zone index value, or
|
|
* the zone instance itself.
|
|
*
|
|
* Prior to v3.60 an Emitter could only have a single Emit Zone and this
|
|
* method was how you set it. From 3.60 and up it now performs a different
|
|
* function and swaps between all available active zones.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setEmitZone
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number|Phaser.GameObjects.Particles.Zones.EdgeZone|Phaser.GameObjects.Particles.Zones.RandomZone} zone - The Emit Zone to set as the active zone.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setEmitZone: function (zone)
|
|
{
|
|
var index;
|
|
|
|
if (isFinite(zone))
|
|
{
|
|
index = zone;
|
|
}
|
|
else
|
|
{
|
|
index = this.emitZones.indexOf(zone);
|
|
}
|
|
|
|
if (index >= 0)
|
|
{
|
|
this.zoneIndex = index;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Adds a Particle Processor, such as a Gravity Well, to this Emitter.
|
|
*
|
|
* It will start processing particles from the next update as long as its `active`
|
|
* property is set.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#addParticleProcessor
|
|
* @since 3.60.0
|
|
*
|
|
* @generic {Phaser.GameObjects.Particles.ParticleProcessor} T
|
|
* @param {T} processor - The Particle Processor to add to this Emitter Manager.
|
|
*
|
|
* @return {T} The Particle Processor that was added to this Emitter Manager.
|
|
*/
|
|
addParticleProcessor: function (processor)
|
|
{
|
|
if (!this.processors.exists(processor))
|
|
{
|
|
if (processor.emitter)
|
|
{
|
|
processor.emitter.removeParticleProcessor(processor);
|
|
}
|
|
|
|
this.processors.add(processor);
|
|
|
|
processor.emitter = this;
|
|
}
|
|
|
|
return processor;
|
|
},
|
|
|
|
/**
|
|
* Removes a Particle Processor from this Emitter.
|
|
*
|
|
* The Processor must belong to this Emitter to be removed.
|
|
*
|
|
* It is not destroyed when removed, allowing you to move it to another Emitter Manager,
|
|
* so if you no longer require it you should call its `destroy` method directly.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#removeParticleProcessor
|
|
* @since 3.60.0
|
|
*
|
|
* @generic {Phaser.GameObjects.Particles.ParticleProcessor} T
|
|
* @param {T} processor - The Particle Processor to remove from this Emitter Manager.
|
|
*
|
|
* @return {?T} The Particle Processor that was removed, or null if it could not be found.
|
|
*/
|
|
removeParticleProcessor: function (processor)
|
|
{
|
|
if (this.processors.exists(processor))
|
|
{
|
|
this.processors.remove(processor, true);
|
|
|
|
processor.emitter = null;
|
|
}
|
|
|
|
return processor;
|
|
},
|
|
|
|
/**
|
|
* Gets all active Particle Processors.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#getProcessors
|
|
* @since 3.60.0
|
|
*
|
|
* @return {Phaser.GameObjects.Particles.ParticleProcessor[]} - An array of active Particle Processors.
|
|
*/
|
|
getProcessors: function ()
|
|
{
|
|
return this.processors.getAll('active', true);
|
|
},
|
|
|
|
/**
|
|
* Creates a new Gravity Well, adds it to this Emitter and returns a reference to it.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#createGravityWell
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.GravityWellConfig} config - Configuration settings for the Gravity Well to create.
|
|
*
|
|
* @return {Phaser.GameObjects.Particles.GravityWell} The Gravity Well that was created.
|
|
*/
|
|
createGravityWell: function (config)
|
|
{
|
|
return this.addParticleProcessor(new GravityWell(config));
|
|
},
|
|
|
|
/**
|
|
* Creates inactive particles and adds them to this emitter's pool.
|
|
*
|
|
* If `ParticleEmitter.maxParticles` is set it will limit the
|
|
* value passed to this method to make sure it's not exceeded.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#reserve
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} count - The number of particles to create.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
reserve: function (count)
|
|
{
|
|
var dead = this.dead;
|
|
|
|
if (this.maxParticles > 0)
|
|
{
|
|
var total = this.getParticleCount();
|
|
|
|
if (total + count > this.maxParticles)
|
|
{
|
|
count = this.maxParticles - (total + count);
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
dead.push(new this.particleClass(this));
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Gets the number of active (in-use) particles in this emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#getAliveParticleCount
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The number of particles with `active=true`.
|
|
*/
|
|
getAliveParticleCount: function ()
|
|
{
|
|
return this.alive.length;
|
|
},
|
|
|
|
/**
|
|
* Gets the number of inactive (available) particles in this emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#getDeadParticleCount
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The number of particles with `active=false`.
|
|
*/
|
|
getDeadParticleCount: function ()
|
|
{
|
|
return this.dead.length;
|
|
},
|
|
|
|
/**
|
|
* Gets the total number of particles in this emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#getParticleCount
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The number of particles, including both alive and dead.
|
|
*/
|
|
getParticleCount: function ()
|
|
{
|
|
return this.getAliveParticleCount() + this.getDeadParticleCount();
|
|
},
|
|
|
|
/**
|
|
* Whether this emitter is at either its hard-cap limit (maxParticles), if set, or
|
|
* the max allowed number of 'alive' particles (maxAliveParticles).
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#atLimit
|
|
* @since 3.0.0
|
|
*
|
|
* @return {boolean} Returns `true` if this Emitter is at its limit, or `false` if no limit, or below the `maxParticles` level.
|
|
*/
|
|
atLimit: function ()
|
|
{
|
|
if (this.maxParticles > 0 && this.getParticleCount() >= this.maxParticles)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return (this.maxAliveParticles > 0 && this.getAliveParticleCount() >= this.maxAliveParticles);
|
|
},
|
|
|
|
/**
|
|
* Sets a function to call for each newly emitted particle.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#onParticleEmit
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.ParticleEmitterCallback} callback - The function.
|
|
* @param {*} [context] - The calling context.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
onParticleEmit: function (callback, context)
|
|
{
|
|
if (callback === undefined)
|
|
{
|
|
// Clear any previously set callback
|
|
this.emitCallback = null;
|
|
this.emitCallbackScope = null;
|
|
}
|
|
else if (typeof callback === 'function')
|
|
{
|
|
this.emitCallback = callback;
|
|
|
|
if (context)
|
|
{
|
|
this.emitCallbackScope = context;
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets a function to call for each particle death.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#onParticleDeath
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.ParticleDeathCallback} callback - The function.
|
|
* @param {*} [context] - The function's calling context.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
onParticleDeath: function (callback, context)
|
|
{
|
|
if (callback === undefined)
|
|
{
|
|
// Clear any previously set callback
|
|
this.deathCallback = null;
|
|
this.deathCallbackScope = null;
|
|
}
|
|
else if (typeof callback === 'function')
|
|
{
|
|
this.deathCallback = callback;
|
|
|
|
if (context)
|
|
{
|
|
this.deathCallbackScope = context;
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Deactivates every particle in this emitter immediately.
|
|
*
|
|
* This particles are killed but do not emit an event or callback.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#killAll
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
killAll: function ()
|
|
{
|
|
var dead = this.dead;
|
|
var alive = this.alive;
|
|
|
|
while (alive.length > 0)
|
|
{
|
|
dead.push(alive.pop());
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calls a function for each active particle in this emitter. The function is
|
|
* sent two parameters: a reference to the Particle instance and to this Emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#forEachAlive
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.ParticleEmitterCallback} callback - The function.
|
|
* @param {*} context - The functions calling context.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
forEachAlive: function (callback, context)
|
|
{
|
|
var alive = this.alive;
|
|
var length = alive.length;
|
|
|
|
for (var i = 0; i < length; i++)
|
|
{
|
|
// Sends the Particle and the Emitter
|
|
callback.call(context, alive[i], this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calls a function for each inactive particle in this emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#forEachDead
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.ParticleEmitterCallback} callback - The function.
|
|
* @param {*} context - The functions calling context.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
forEachDead: function (callback, context)
|
|
{
|
|
var dead = this.dead;
|
|
var length = dead.length;
|
|
|
|
for (var i = 0; i < length; i++)
|
|
{
|
|
callback.call(context, dead[i], this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Turns {@link Phaser.GameObjects.Particles.ParticleEmitter#on} the emitter and resets the flow counter.
|
|
*
|
|
* If this emitter is in flow mode (frequency >= 0; the default), the particle flow will start (or restart).
|
|
*
|
|
* If this emitter is in explode mode (frequency = -1), nothing will happen.
|
|
* Use {@link Phaser.GameObjects.Particles.ParticleEmitter#explode} or {@link Phaser.GameObjects.Particles.ParticleEmitter#flow} instead.
|
|
*
|
|
* Calling this method will emit the `START` event.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#start
|
|
* @fires Phaser.GameObjects.Particles.Events#START
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [advance=0] - Advance this number of ms in time through the emitter.
|
|
* @param {number} [duration=0] - Limit this emitter to only emit particles for the given number of ms. Setting this parameter will override any duration already set in the Emitter configuration object.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
start: function (advance, duration)
|
|
{
|
|
if (advance === undefined) { advance = 0; }
|
|
|
|
if (!this.emitting)
|
|
{
|
|
if (advance > 0)
|
|
{
|
|
this.fastForward(advance);
|
|
}
|
|
|
|
this.emitting = true;
|
|
|
|
this.resetCounters(this.frequency, true);
|
|
|
|
if (duration !== undefined)
|
|
{
|
|
this.duration = Math.abs(duration);
|
|
}
|
|
|
|
this.emit(Events.START, this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Turns {@link Phaser.GameObjects.Particles.ParticleEmitter#emitting off} the emitter and
|
|
* stops it from emitting further particles. Currently alive particles will remain
|
|
* active until they naturally expire unless you set the `kill` parameter to `true`.
|
|
*
|
|
* Calling this method will emit the `STOP` event. When the final particle has
|
|
* expired the `COMPLETE` event will be emitted.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#stop
|
|
* @fires Phaser.GameObjects.Particles.Events#STOP
|
|
* @since 3.11.0
|
|
*
|
|
* @param {boolean} [kill=false] - Kill all particles immediately (true), or leave them to die after their lifespan expires? (false, the default)
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
stop: function (kill)
|
|
{
|
|
if (kill === undefined) { kill = false; }
|
|
|
|
if (this.emitting)
|
|
{
|
|
this.emitting = false;
|
|
|
|
if (kill)
|
|
{
|
|
this.killAll();
|
|
}
|
|
|
|
this.emit(Events.STOP, this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* {@link Phaser.GameObjects.Particles.ParticleEmitter#active Deactivates} the emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#pause
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
pause: function ()
|
|
{
|
|
this.active = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* {@link Phaser.GameObjects.Particles.ParticleEmitter#active Activates} the emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#resume
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
resume: function ()
|
|
{
|
|
this.active = true;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the property by which active particles are sorted prior to be rendered.
|
|
*
|
|
* It allows you to control the rendering order of the particles.
|
|
*
|
|
* This can be any valid property of the `Particle` class, such as `y`, `alpha`
|
|
* or `lifeT`.
|
|
*
|
|
* The 'alive' particles array is sorted in place each game frame. Setting a
|
|
* sort property will override the `particleBringToTop` setting.
|
|
*
|
|
* If you wish to use your own sorting function, see `setSortCallback` instead.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setSortProperty
|
|
* @since 3.60.0
|
|
*
|
|
* @param {string} [property] - The property on the `Particle` class to sort by.
|
|
* @param {boolean} [ascending=true] - Should the particles be sorted in ascending or descending order?
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setSortProperty: function (property, ascending)
|
|
{
|
|
if (property === undefined) { property = ''; }
|
|
if (ascending === undefined) { ascending = this.true; }
|
|
|
|
this.sortProperty = property;
|
|
this.sortOrderAsc = ascending;
|
|
this.sortCallback = this.depthSortCallback;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets a callback to be used to sort the particles before rendering each frame.
|
|
*
|
|
* This allows you to define your own logic and behavior in the callback.
|
|
*
|
|
* The callback will be sent two parameters: the two Particles being compared,
|
|
* and must adhere to the criteria of the `compareFn` in `Array.sort`:
|
|
*
|
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#description
|
|
*
|
|
* Call this method with no parameters to reset the sort callback.
|
|
*
|
|
* Setting your own callback will override both the `particleBringToTop` and
|
|
* `sortProperty` settings of this Emitter.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#setSortCallback
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Types.GameObjects.Particles.ParticleSortCallback} [callback] - The callback to invoke when the particles are sorted. Leave undefined to reset to the default.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
setSortCallback: function (callback)
|
|
{
|
|
if (this.sortProperty !== '')
|
|
{
|
|
callback = this.depthSortCallback;
|
|
}
|
|
else
|
|
{
|
|
callback = null;
|
|
}
|
|
|
|
this.sortCallback = callback;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sorts active particles with {@link Phaser.GameObjects.Particles.ParticleEmitter#depthSortCallback}.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#depthSort
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
depthSort: function ()
|
|
{
|
|
StableSort(this.alive, this.sortCallback.bind(this));
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculates the difference of two particles, for sorting them by depth.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#depthSortCallback
|
|
* @since 3.0.0
|
|
*
|
|
* @param {object} a - The first particle.
|
|
* @param {object} b - The second particle.
|
|
*
|
|
* @return {number} The difference of a and b's y coordinates.
|
|
*/
|
|
depthSortCallback: function (a, b)
|
|
{
|
|
var key = this.sortProperty;
|
|
|
|
if (this.sortOrderAsc)
|
|
{
|
|
return a[key] - b[key];
|
|
}
|
|
else
|
|
{
|
|
return b[key] - a[key];
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Puts the emitter in flow mode (frequency >= 0) and starts (or restarts) a particle flow.
|
|
*
|
|
* To resume a flow at the current frequency and quantity, use {@link Phaser.GameObjects.Particles.ParticleEmitter#start} instead.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#flow
|
|
* @fires Phaser.GameObjects.Particles.Events#START
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} frequency - The time interval (>= 0) of each flow cycle, in ms.
|
|
* @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} [count=1] - The number of particles to emit at each flow cycle.
|
|
* @param {number} [stopAfter] - Stop this emitter from firing any more particles once this value is reached. Set to zero for unlimited. Setting this parameter will override any `stopAfter` value already set in the Emitter configuration object.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
flow: function (frequency, count, stopAfter)
|
|
{
|
|
if (count === undefined) { count = 1; }
|
|
|
|
this.emitting = false;
|
|
|
|
this.frequency = frequency;
|
|
this.quantity = count;
|
|
|
|
if (stopAfter !== undefined)
|
|
{
|
|
this.stopAfter = stopAfter;
|
|
}
|
|
|
|
return this.start();
|
|
},
|
|
|
|
/**
|
|
* Puts the emitter in explode mode (frequency = -1), stopping any current particle flow, and emits several particles all at once.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#explode
|
|
* @fires Phaser.GameObjects.Particles.Events#EXPLODE
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [count=this.quantity] - The number of Particles to emit.
|
|
* @param {number} [x=this.x] - The x coordinate to emit the Particles from.
|
|
* @param {number} [y=this.x] - The y coordinate to emit the Particles from.
|
|
*
|
|
* @return {Phaser.GameObjects.Particles.Particle} The most recently emitted Particle.
|
|
*/
|
|
explode: function (count, x, y)
|
|
{
|
|
this.frequency = -1;
|
|
|
|
this.resetCounters(-1, true);
|
|
|
|
var particle = this.emitParticle(count, x, y);
|
|
|
|
this.emit(Events.EXPLODE, this, particle);
|
|
|
|
return particle;
|
|
},
|
|
|
|
/**
|
|
* Emits particles at the given position. If no position is given, it will
|
|
* emit from this Emitters current location.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#emitParticleAt
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x=this.x] - The x coordinate to emit the Particles from.
|
|
* @param {number} [y=this.x] - The y coordinate to emit the Particles from.
|
|
* @param {number} [count=this.quantity] - The number of Particles to emit.
|
|
*
|
|
* @return {Phaser.GameObjects.Particles.Particle} The most recently emitted Particle.
|
|
*/
|
|
emitParticleAt: function (x, y, count)
|
|
{
|
|
return this.emitParticle(count, x, y);
|
|
},
|
|
|
|
/**
|
|
* Emits particles at a given position (or the emitters current position).
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#emitParticle
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [count=this.quantity] - The number of Particles to emit.
|
|
* @param {number} [x=this.x] - The x coordinate to emit the Particles from.
|
|
* @param {number} [y=this.x] - The y coordinate to emit the Particles from.
|
|
*
|
|
* @return {Phaser.GameObjects.Particles.Particle} The most recently emitted Particle.
|
|
*
|
|
* @see Phaser.GameObjects.Particles.Particle#fire
|
|
*/
|
|
emitParticle: function (count, x, y)
|
|
{
|
|
if (this.atLimit())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (count === undefined)
|
|
{
|
|
count = this.ops.quantity.onEmit();
|
|
}
|
|
|
|
var dead = this.dead;
|
|
var stopAfter = this.stopAfter;
|
|
|
|
var followX = (this.follow) ? this.follow.x + this.followOffset.x : x;
|
|
var followY = (this.follow) ? this.follow.y + this.followOffset.y : y;
|
|
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
var particle = dead.pop();
|
|
|
|
if (!particle)
|
|
{
|
|
particle = new this.particleClass(this);
|
|
}
|
|
|
|
if (particle.fire(followX, followY))
|
|
{
|
|
if (this.particleBringToTop)
|
|
{
|
|
this.alive.push(particle);
|
|
}
|
|
else
|
|
{
|
|
this.alive.unshift(particle);
|
|
}
|
|
|
|
if (this.emitCallback)
|
|
{
|
|
this.emitCallback.call(this.emitCallbackScope, particle, this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.dead.push(particle);
|
|
}
|
|
|
|
if (stopAfter > 0)
|
|
{
|
|
this.stopCounter++;
|
|
|
|
if (this.stopCounter >= stopAfter)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (this.atLimit())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return particle;
|
|
},
|
|
|
|
/**
|
|
* Fast forwards this Particle Emitter and all of its particles.
|
|
*
|
|
* Works by running the Emitter `preUpdate` handler in a loop until the `time`
|
|
* has been reached at `delta` steps per loop.
|
|
*
|
|
* All callbacks and emitter related events that would normally be fired
|
|
* will still be invoked.
|
|
*
|
|
* You can make an emitter 'fast forward' via the emitter config using the
|
|
* `advance` property. Set this value to the number of ms you wish the
|
|
* emitter to be fast-forwarded by. Or, call this method post-creation.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#fastForward
|
|
* @since 3.60.0
|
|
*
|
|
* @param {number} time - The number of ms to advance the Particle Emitter by.
|
|
* @param {number} [delta] - The amount of delta to use for each step. Defaults to 1000 / 60.
|
|
*
|
|
* @return {this} This Particle Emitter.
|
|
*/
|
|
fastForward: function (time, delta)
|
|
{
|
|
if (delta === undefined) { delta = 1000 / 60; }
|
|
|
|
var total = 0;
|
|
|
|
this.skipping = true;
|
|
|
|
while (total < Math.abs(time))
|
|
{
|
|
this.preUpdate(0, delta);
|
|
|
|
total += delta;
|
|
}
|
|
|
|
this.skipping = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Updates this emitter and its particles.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#preUpdate
|
|
* @fires Phaser.GameObjects.Particles.Events#COMPLETE
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout.
|
|
* @param {number} delta - The delta time, in ms, elapsed since the last frame.
|
|
*/
|
|
preUpdate: function (time, delta)
|
|
{
|
|
// Scale the delta
|
|
delta *= this.timeScale;
|
|
|
|
var step = (delta / 1000);
|
|
|
|
if (this.trackVisible)
|
|
{
|
|
this.visible = this.follow.visible;
|
|
}
|
|
|
|
this.getWorldTransformMatrix(this.worldMatrix);
|
|
|
|
// Any particle processors?
|
|
var processors = this.getProcessors();
|
|
|
|
var particles = this.alive;
|
|
var dead = this.dead;
|
|
|
|
var i = 0;
|
|
var rip = [];
|
|
var length = particles.length;
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
var particle = particles[i];
|
|
|
|
// update returns `true` if the particle is now dead (lifeCurrent <= 0)
|
|
if (particle.update(delta, step, processors))
|
|
{
|
|
rip.push({ index: i, particle: particle });
|
|
}
|
|
}
|
|
|
|
// Move dead particles to the dead array
|
|
length = rip.length;
|
|
|
|
if (length > 0)
|
|
{
|
|
var deathCallback = this.deathCallback;
|
|
var deathCallbackScope = this.deathCallbackScope;
|
|
|
|
for (i = length - 1; i >= 0; i--)
|
|
{
|
|
var entry = rip[i];
|
|
|
|
// Remove from particles array
|
|
particles.splice(entry.index, 1);
|
|
|
|
// Add to dead array
|
|
dead.push(entry.particle);
|
|
|
|
// Callback
|
|
if (deathCallback)
|
|
{
|
|
deathCallback.call(deathCallbackScope, entry.particle);
|
|
}
|
|
|
|
entry.particle.setPosition();
|
|
}
|
|
}
|
|
|
|
if (!this.emitting && !this.skipping)
|
|
{
|
|
if (this.completeFlag === 1 && particles.length === 0)
|
|
{
|
|
this.completeFlag = 0;
|
|
|
|
this.emit(Events.COMPLETE, this);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (this.frequency === 0)
|
|
{
|
|
this.emitParticle();
|
|
}
|
|
else if (this.frequency > 0)
|
|
{
|
|
this.flowCounter -= delta;
|
|
|
|
while (this.flowCounter <= 0)
|
|
{
|
|
// Emits the 'quantity' number of particles
|
|
this.emitParticle();
|
|
|
|
// counter = frequency - remainder from previous delta
|
|
this.flowCounter += this.frequency;
|
|
}
|
|
}
|
|
|
|
// Duration or stopAfter set?
|
|
if (!this.skipping)
|
|
{
|
|
if (this.duration > 0)
|
|
{
|
|
// elapsed
|
|
this.elapsed += delta;
|
|
|
|
if (this.elapsed >= this.duration)
|
|
{
|
|
this.stop();
|
|
}
|
|
}
|
|
|
|
if (this.stopAfter > 0 && this.stopCounter >= this.stopAfter)
|
|
{
|
|
this.stop();
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Takes either a Rectangle Geometry object or an Arcade Physics Body and tests
|
|
* to see if it intersects with any currently alive Particle in this Emitter.
|
|
*
|
|
* Overlapping particles are returned in an array, where you can perform further
|
|
* processing on them. If nothing overlaps then the array will be empty.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#overlap
|
|
* @since 3.60.0
|
|
*
|
|
* @param {(Phaser.Geom.Rectangle|Phaser.Physics.Arcade.Body)} target - A Rectangle or Arcade Physics Body to check for intersection against all alive particles.
|
|
*
|
|
* @return {Phaser.GameObjects.Particles.Particle[]} An array of Particles that overlap with the given target.
|
|
*/
|
|
overlap: function (target)
|
|
{
|
|
var matrix = this.getWorldTransformMatrix();
|
|
|
|
var alive = this.alive;
|
|
var length = alive.length;
|
|
|
|
var output = [];
|
|
|
|
for (var i = 0; i < length; i++)
|
|
{
|
|
var particle = alive[i];
|
|
|
|
if (RectangleToRectangle(target, particle.getBounds(matrix)))
|
|
{
|
|
output.push(particle);
|
|
}
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Returns a bounds Rectangle calculated from the bounds of all currently
|
|
* _active_ Particles in this Emitter. If this Emitter has only just been
|
|
* created and not yet rendered, then calling this method will return a Rectangle
|
|
* with a max safe integer for dimensions. Use the `advance` parameter to
|
|
* avoid this.
|
|
*
|
|
* Typically it takes a few seconds for a flow Emitter to 'warm up'. You can
|
|
* use the `advance` and `delta` parameters to force the Emitter to
|
|
* 'fast forward' in time to try and allow the bounds to be more accurate,
|
|
* as it will calculate the bounds based on the particle bounds across all
|
|
* timesteps, giving a better result.
|
|
*
|
|
* You can also use the `padding` parameter to increase the size of the
|
|
* bounds. Emitters with a lot of randomness in terms of direction or lifespan
|
|
* can often return a bounds smaller than their possible maximum. By using
|
|
* the `padding` (and `advance` if needed) you can help limit this.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#getBounds
|
|
* @since 3.60.0
|
|
*
|
|
* @param {number} [padding] - The amount of padding, in pixels, to add to the bounds Rectangle.
|
|
* @param {number} [advance] - The number of ms to advance the Particle Emitter by. Defaults to 0, i.e. not used.
|
|
* @param {number} [delta] - The amount of delta to use for each step. Defaults to 1000 / 60.
|
|
* @param {Phaser.Geom.Rectangle} [output] - The Rectangle to store the results in. If not given a new one will be created.
|
|
*
|
|
* @return {Phaser.Geom.Rectangle} A Rectangle containing the calculated bounds of this Emitter.
|
|
*/
|
|
getBounds: function (padding, advance, delta, output)
|
|
{
|
|
if (padding === undefined) { padding = 0; }
|
|
if (advance === undefined) { advance = 0; }
|
|
if (delta === undefined) { delta = 1000 / 60; }
|
|
if (output === undefined) { output = new Rectangle(); }
|
|
|
|
var matrix = this.getWorldTransformMatrix();
|
|
|
|
var i;
|
|
var bounds;
|
|
var alive = this.alive;
|
|
var setFirst = false;
|
|
|
|
output.setTo(0, 0, 0, 0);
|
|
|
|
if (advance > 0)
|
|
{
|
|
var total = 0;
|
|
|
|
this.skipping = true;
|
|
|
|
while (total < Math.abs(advance))
|
|
{
|
|
this.preUpdate(0, delta);
|
|
|
|
for (i = 0; i < alive.length; i++)
|
|
{
|
|
bounds = alive[i].getBounds(matrix);
|
|
|
|
if (!setFirst)
|
|
{
|
|
setFirst = true;
|
|
|
|
CopyFrom(bounds, output);
|
|
}
|
|
else
|
|
{
|
|
MergeRect(output, bounds);
|
|
}
|
|
}
|
|
|
|
total += delta;
|
|
}
|
|
|
|
this.skipping = false;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < alive.length; i++)
|
|
{
|
|
bounds = alive[i].getBounds(matrix);
|
|
|
|
if (!setFirst)
|
|
{
|
|
setFirst = true;
|
|
|
|
CopyFrom(bounds, output);
|
|
}
|
|
else
|
|
{
|
|
MergeRect(output, bounds);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (padding > 0)
|
|
{
|
|
Inflate(output, padding, padding);
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Prints a warning to the console if you mistakenly call this function
|
|
* thinking it works the same way as Phaser v3.55.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#createEmitter
|
|
* @since 3.60.0
|
|
*/
|
|
createEmitter: function ()
|
|
{
|
|
throw new Error('createEmitter removed. See ParticleEmitter docs for info');
|
|
},
|
|
|
|
/**
|
|
* The x coordinate the particles are emitted from.
|
|
*
|
|
* This is relative to the Emitters x coordinate and that of any parent.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleX
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType}
|
|
* @since 3.60.0
|
|
*/
|
|
particleX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.x.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.x.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The y coordinate the particles are emitted from.
|
|
*
|
|
* This is relative to the Emitters x coordinate and that of any parent.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleY
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType}
|
|
* @since 3.60.0
|
|
*/
|
|
particleY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.y.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.y.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The horizontal acceleration applied to emitted particles, in pixels per second squared.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#accelerationX
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
accelerationX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.accelerationX.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.accelerationX.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The vertical acceleration applied to emitted particles, in pixels per second squared.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#accelerationY
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
accelerationY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.accelerationY.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.accelerationY.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The maximum horizontal velocity emitted particles can reach, in pixels per second squared.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#maxVelocityX
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
* @default 10000
|
|
*/
|
|
maxVelocityX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.maxVelocityX.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.maxVelocityX.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The maximum vertical velocity emitted particles can reach, in pixels per second squared.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#maxVelocityY
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
* @default 10000
|
|
*/
|
|
maxVelocityY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.maxVelocityY.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.maxVelocityY.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The initial speed of emitted particles, in pixels per second.
|
|
*
|
|
* If using this as a getter it will return the `speedX` value.
|
|
*
|
|
* If using it as a setter it will update both `speedX` and `speedY` to the
|
|
* given value.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#speed
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
speed: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.speedX.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.speedX.onChange(value);
|
|
this.ops.speedY.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The initial horizontal speed of emitted particles, in pixels per second.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#speedX
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
speedX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.speedX.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.speedX.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The initial vertical speed of emitted particles, in pixels per second.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#speedY
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
speedY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.speedY.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.speedY.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The x coordinate emitted particles move toward, when {@link Phaser.GameObjects.Particles.ParticleEmitter#moveTo} is true.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#moveToX
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
moveToX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.moveToX.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.moveToX.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The y coordinate emitted particles move toward, when {@link Phaser.GameObjects.Particles.ParticleEmitter#moveTo} is true.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#moveToY
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
moveToY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.moveToY.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.moveToY.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The amount of velocity particles will use when rebounding off the
|
|
* emitter bounds, if set. A value of 0 means no bounce. A value of 1
|
|
* means a full rebound.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#bounce
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
bounce: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.bounce.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.bounce.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The horizontal scale of emitted particles.
|
|
*
|
|
* This is relative to the Emitters scale and that of any parent.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleScaleX
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
particleScaleX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.scaleX.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.scaleX.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The vertical scale of emitted particles.
|
|
*
|
|
* This is relative to the Emitters scale and that of any parent.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleScaleY
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
particleScaleY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.scaleY.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.scaleY.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* A color tint value that is applied to the texture of the emitted
|
|
* particle. The value should be given in hex format, i.e. 0xff0000
|
|
* for a red tint, and should not include the alpha channel.
|
|
*
|
|
* Tints are additive, meaning a tint value of white (0xffffff) will
|
|
* effectively reset the tint to nothing.
|
|
*
|
|
* Modify the `ParticleEmitter.tintFill` property to change between
|
|
* an additive and replacement tint mode.
|
|
*
|
|
* When you define the color via the Emitter config you should give
|
|
* it as an array of color values. The Particle will then interpolate
|
|
* through these colors over the course of its lifespan. Setting this
|
|
* will override any `tint` value that may also be given.
|
|
*
|
|
* This is a WebGL only feature.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleColor
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
particleColor: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.color.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.color.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Controls the easing function used when you have created an
|
|
* Emitter that uses the `color` property to interpolate the
|
|
* tint of Particles over their lifetime.
|
|
*
|
|
* Setting this has no effect if you haven't also applied a
|
|
* `particleColor` to this Emitter.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#colorEase
|
|
* @type {string}
|
|
* @since 3.60.0
|
|
*/
|
|
colorEase: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.color.easeName;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.color.setEase(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* A color tint value that is applied to the texture of the emitted
|
|
* particle. The value should be given in hex format, i.e. 0xff0000
|
|
* for a red tint, and should not include the alpha channel.
|
|
*
|
|
* Tints are additive, meaning a tint value of white (0xffffff) will
|
|
* effectively reset the tint to nothing.
|
|
*
|
|
* Modify the `ParticleEmitter.tintFill` property to change between
|
|
* an additive and replacement tint mode.
|
|
*
|
|
* The `tint` value will be overriden if a `color` array is provided.
|
|
*
|
|
* This is a WebGL only feature.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleTint
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
particleTint: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.tint.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.tint.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The alpha value of the emitted particles. This is a value
|
|
* between 0 and 1. Particles with alpha zero are invisible
|
|
* and are therefore not rendered, but are still processed
|
|
* by the Emitter.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleAlpha
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
particleAlpha: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.alpha.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.alpha.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The lifespan of the emitted particles. This value is given
|
|
* in milliseconds and defaults to 1000ms (1 second). When a
|
|
* particle reaches this amount it is killed.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#lifespan
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
lifespan: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.lifespan.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.lifespan.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The angle at which the particles are emitted. The values are
|
|
* given in degrees. This allows you to control the direction
|
|
* of the emitter. If you wish instead to change the rotation
|
|
* of the particles themselves, see the `particleRotate` property.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleAngle
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
particleAngle: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.angle.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.angle.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The rotation (or angle) of each particle when it is emitted.
|
|
* The value is given in degrees and uses a right-handed
|
|
* coordinate system, where 0 degrees points to the right, 90 degrees
|
|
* points down and -90 degrees points up.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#particleRotate
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
particleRotate: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.rotate.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.rotate.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The number of particles that are emitted each time an emission
|
|
* occurs, i.e. from one 'explosion' or each frame in a 'flow' cycle.
|
|
*
|
|
* The default is 1.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#quantity
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setFrequency
|
|
* @see Phaser.GameObjects.Particles.ParticleEmitter#setQuantity
|
|
* @since 3.60.0
|
|
*/
|
|
quantity: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.quantity.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.quantity.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The number of milliseconds to wait after emission before
|
|
* the particles start updating. This allows you to emit particles
|
|
* that appear 'static' or still on-screen and then, after this value,
|
|
* begin to move.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#delay
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
delay: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.delay.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.delay.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The number of milliseconds to wait after a particle has finished
|
|
* its life before it will be removed. This allows you to 'hold' a
|
|
* particle on the screen once it has reached its final state
|
|
* before it then vanishes.
|
|
*
|
|
* Note that all particle updates will cease, including changing
|
|
* alpha, scale, movement or animation.
|
|
*
|
|
* Accessing this property should typically return a number.
|
|
* However, it can be set to any valid EmitterOp onEmit type.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#hold
|
|
* @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType}
|
|
* @since 3.60.0
|
|
*/
|
|
hold: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.ops.hold.current;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.ops.hold.onChange(value);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The internal flow counter.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#flowCounter
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
flowCounter: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[0];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[0] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The internal frame counter.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#frameCounter
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
frameCounter: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[1];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[1] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The internal animation counter.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#animCounter
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
animCounter: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[2];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[2] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The internal elasped counter.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#elapsed
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
elapsed: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[3];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[3] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The internal stop counter.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#stopCounter
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
stopCounter: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[4];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[4] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The internal complete flag.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#completeFlag
|
|
* @type {boolean}
|
|
* @since 3.60.0
|
|
*/
|
|
completeFlag: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[5];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[5] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The internal zone index.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#zoneIndex
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
zoneIndex: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[6];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[6] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The internal zone total.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#zoneTotal
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
zoneTotal: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[7];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[7] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The current frame index.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#currentFrame
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
currentFrame: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[8];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[8] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The current animation index.
|
|
*
|
|
* Treat this property as read-only.
|
|
*
|
|
* @name Phaser.GameObjects.Particles.ParticleEmitter#currentAnim
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
currentAnim: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.counters[9];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.counters[9] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Destroys this Particle Emitter and all Particles it owns.
|
|
*
|
|
* @method Phaser.GameObjects.Particles.ParticleEmitter#preDestroy
|
|
* @since 3.60.0
|
|
*/
|
|
preDestroy: function ()
|
|
{
|
|
this.texture = null;
|
|
this.frames = null;
|
|
this.anims = null;
|
|
this.emitCallback = null;
|
|
this.emitCallbackScope = null;
|
|
this.deathCallback = null;
|
|
this.deathCallbackScope = null;
|
|
this.emitZones = null;
|
|
this.deathZones = null;
|
|
this.bounds = null;
|
|
this.follow = null;
|
|
this.counters = null;
|
|
|
|
var i;
|
|
|
|
var ops = this.ops;
|
|
|
|
for (i = 0; i < configOpMap.length; i++)
|
|
{
|
|
var key = configOpMap[i];
|
|
|
|
ops[key].destroy();
|
|
}
|
|
|
|
for (i = 0; i < this.alive.length; i++)
|
|
{
|
|
this.alive[i].destroy();
|
|
}
|
|
|
|
for (i = 0; i < this.dead.length; i++)
|
|
{
|
|
this.dead[i].destroy();
|
|
}
|
|
|
|
this.ops = null;
|
|
this.alive = [];
|
|
this.dead = [];
|
|
this.worldMatrix.destroy();
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = ParticleEmitter;
|