Skip to content

Particles

The @yagejs/particles package provides a lightweight particle system with pooled rendering, configurable emitters, and built-in presets for common effects.

import { ParticlesPlugin } from "@yagejs/particles";
engine.use(new ParticlesPlugin());

The plugin depends on @yagejs/renderer.

Add a ParticleEmitterComponent to an entity. Particles spawn at the entity’s Transform position.

import { ParticleEmitterComponent } from "@yagejs/particles";
import { texture } from "@yagejs/renderer";
const Particle = texture("assets/particle.png");
const emitter = new ParticleEmitterComponent({
texture: Particle,
maxParticles: 200,
rate: 20, // particles per second
lifetime: [0.5, 1.5], // seconds (random range)
speed: [50, 150], // px/s
angle: [-Math.PI, Math.PI], // emission direction (radians)
scale: { start: 1, end: 0 },
alpha: { start: 1, end: 0 },
tint: 0xff6600,
gravity: { x: 0, y: 200 },
layer: "effects",
});
entity.add(emitter);
emitter.emit(); // start continuous emission
PropertyTypeDefaultDescription
textureTextureInputParticle texture
textureKeystringAsset key (serializable alternative to texture)
maxParticlesnumber100Maximum live particles
ratenumber10Emission rate (particles/sec)
lifetimeNumberRangeParticle lifetime in seconds (required)
speedNumberRange0Initial speed (px/s)
angleNumberRange0Emission angle (radians)
scaleNumberRange | Lerped1Size, or start→end interpolation
alphaNumberRange | Lerped1Opacity, or start→end interpolation
rotationNumberRange0Initial rotation (radians)
rotationSpeedNumberRange0Rotation speed (rad/s)
tintnumber0xffffffColor tint
gravity{ x, y }Per-particle gravity (px/s²)
dampingnumber0Velocity damping (0–1)
spawnOffset{ x?, y? }Random offset from emitter position
layerstring"default"Render layer name

NumberRange can be a single number or a [min, max] tuple for random values.

Lerped interpolates from start to end over the particle’s lifetime:

scale: { start: [0.8, 1.2], end: 0 } // shrink to nothing
alpha: { start: 1, end: [0, 0.3] } // fade out with variation
emitter.emit(); // start continuous emission
emitter.stop(); // stop emitting (existing particles continue)
emitter.burst(50); // spawn 50 particles immediately
emitter.burst(10, 400, 300); // burst at specific world position
emitter.isEmitting; // boolean
emitter.activeCount; // number of live particles

ParticlePresets provides ready-made configs for common effects. Each preset takes a texture and returns a complete EmitterConfig:

import { ParticlePresets } from "@yagejs/particles";
// Fire — upward, warm colors, shrinking
entity.add(new ParticleEmitterComponent(ParticlePresets.fire(Particle)));
// Smoke — slow, expanding, fading
entity.add(new ParticleEmitterComponent(ParticlePresets.smoke(Particle)));
// Sparks — fast, short-lived, gravity-affected
entity.add(new ParticleEmitterComponent(ParticlePresets.sparks(Particle)));
// Rain — downward, uniform, long-lived
entity.add(new ParticleEmitterComponent(ParticlePresets.rain(Particle)));

You can spread a preset and override specific properties:

entity.add(new ParticleEmitterComponent({
...ParticlePresets.fire(Particle),
rate: 50,
tint: 0x00ccff, // blue fire
}));
  • Position the emitter entity where you want particles to spawn — particles inherit the entity’s world position at the moment they’re created.
  • Destroying the emitter entity stops emission and cleans up all particles.
  • Keep maxParticles reasonable. Hundreds are fine; thousands may impact performance on lower-end devices.
  • Use render layers to control whether particles appear above or below game entities.