Skip to content

Particles

samme edited this page Oct 17, 2022 · 43 revisions

Flare particles burst

Particles are fun and not so difficult, but there are a lot of details. Read the docs and examples closely.

Particle manager

const manager = this.add.particles('textureKey');

A particle manager is the actual game object on the scene display list and update list. You can change its position, rotation, scale, alpha, visibility, and depth like other game objects. The transform point is the manager's position, (0, 0) by default.

You can add or remove emitters at any time.

Particle emitter

const emitter1 = manager.createEmitter(config);

You can reconfigure an emitter at any time with fromJSON(config), or set individual properties by method, e.g. setPosition(x, y).

Emitters are on when created unless you use { on: false }.

Particles last for lifespan and then disappear. The default lifespan is 1000 ms.

An emitter's emitCallback and deathCallback are called at the start and end of each particle's life.

Flow

Emitters in flow mode (the default mode) release particles periodically, based on frequency and quantity. The flow can be on or off. Phaser's frequency is actually a time interval (period) so the true frequency is 1000 / frequency. The particle flow per second is

1000 * quantity / frequency

The default frequency is 0, which means every update, but since that can vary depending on the game loop delta, you may want to give an explicit value instead. Values below 16 or so may also give inconsistent results.

You can stop emitter flow with stop() and restart with start(), or toggle the emitter's on property. start() starts a new flow cycle immediately.

Explode

explode(count, x, y) switches out of flow mode and releases particles immediately. It uses the passed values or the current values from the emitter.

When using explode() you really need only one particle emitter, and you can reconfigure any of its values each time if you want. For example, in Fireworks 4, an emitter is positioned and tinted for each burst:

emitter
  .setPosition(1024 * FloatBetween(0.25, 0.75), 768 * FloatBetween(0, 0.5))
  .setTint(GetRandom(tints))
  .explode();

Emit particles manually

emitParticle(count, x, y) works like explode() but it doesn't switch the emitter out of flow mode. emitParticleAt(x, y, count) is the same but with a different argument order.

Motion

Particles are "fired" from the emitter with a velocity determined by

  • the moveToX and moveToY coordinates if set; or
  • speedX and speedY if set (point); or
  • angle and speed (radial)

With moveTo the particles move continuously toward the target coordinates and arrive at the end of their life.

Emitter ops

Emitter ops (operations? operators? — we will never know) can hold a single value or a rule for generating a value.

For "emit-only" ops you can give a single value, a random range, a stepped range, or a custom function.

For the other ops you can give a random range or a stepped range (for the emit phase); or a single value, an eased range, or a custom function (for the update phase); or an object with onEmit and onUpdate to work in both phases.

These will make more sense if you look at the examples.

The ops value (number, array, function, or object) is in its propertyValue, e.g., emitter.x.propertyValue.

Only a few properties are updatable:

Emit Phase Update Phase
accelerationX
accelerationY
alpha alpha
angle
bounce
delay
lifespan
maxVelocityX
maxVelocityY
moveToX
moveToY
quantity
rotate rotate
scaleX scaleX
scaleY scaleY
speedX
speedY
tint tint

Easings

Ops with an update phase can be eased, e.g.,

emitter.setAlpha({ start: 0, end: 1 });

The ease duration is the particle lifespan. You can use your own easing function for customization:

Yoyo ease
const Ease = Phaser.Math.Easing.Quadratic.In;

emitter.setAlpha({
  start: 0,
  end: 1,
  ease: (t) => 0.5 * Ease(t > 0.5 ? 2 - 2 * t : 2 * t)
});

Stepped ranges

Four emitters with stepped angle

A stepped range advances at one step per particle emit, so the step cycle interval (start to end) is

frequency * steps / quantity

For example,

{ frequency: 10, quantity: 1, angle: { start: 0, end: 360, steps: 100 } }

will step the angle from 0 to 360° over 1 second (1000 ms == 10 ms * 100 steps / 1). Visually the angle is "moving" through one turn (3.6° per 10ms).

When quantity equals steps, the whole range is encompassed at once, making a uniform spread. For example,

{ frequency: 1000, quantity: 100, angle: { start: 0, end: 360, steps: 100 } }

makes a burst of 100 particles every second.

Death zones

They kill the particles when they enter or leave the zone (as you specify). Position the zone accordingly!

Emit zones

Random emit zones release each particle at a random position given by a source. The source can be a Geom shape, path, curve, or anything with a getRandomPoint(point) method. Geom sources give a random position within their area. getRandomPoint(point) is called each time a particle is released.

Edge emit zones release each particle from a sequence of positions given by a source. The source can be a Geom shape, path, curve, or anything with a getPoints(quantity, stepRate) method. Geom sources place the points on their edges, start to end. The point sequence is generated once when the zone is created; you can call edgeZone.updateSource() to create a new sequence.

Bounds

When set the particles bounce off the interior edges, depending on the emitter bounce.

Gravity wells

Gravity wells can be added to the particle manager.

manager.createGravityWell({ x: 0, y: 0, power: 2, epsilon: 100, gravity: 50 });

Particles

You receive a particle in an emitter's deathCallback and emitCallback callbacks; an emitter op's onEmit and onUpdate callbacks, and a gravity well's update callbacks.

  • lifeT is the particle's standardized life, from 0 (start) to 1 (end).
  • life is its lifespan (i.e., maximum) in ms.
  • lifeCurrent is its current life in ms, decreasing from life to 0.
  • life - lifeCurrent is its current life in ms, increasing from 0.
Clone this wiki locally