Skip to main content

Particle Layer

Hs2dParticleLayer wraps a CompositorParticleSystem and feeds it camera-projected emitters. The particle system owns a fixed pool of compositor sprites hosted on an existing sprite layer compositor. Expired particles are hidden and parked offscreen; new emissions reuse inactive pool entries.

Particles are gameplay visuals and should use this fixed pool path. Do not draw particle loops directly to the screen each frame.

When To Use

Use a particle layer for:

UseNotes
Sparks, fire, explosions, rocket fire, lasers, missiles, camera sparkle, dustBuilt-in emitter kinds are defined by NativeRigParticleEmitterKind.
Short-lived repeated effectsUse updateEmitters through Hs2dParticleLayer.update.
One-shot burstsUse emitForEmitter with a temporary emitter object.

Use sprite pools for long-lived projectiles or gameplay actors. Particles are visual effects, not entity ownership.

Construction Pattern

Create a host sprite layer first, then add particles to it:

const foreground = world.addHs2dSpriteLayer({
id: 'foreground',
width: screenWidth,
height: screenHeight,
offscreenX: -1000,
offscreenY: -1000,
});

this.particles = world.addParticleLayer({
id: 'ship-particles',
layer: foreground,
regions: createDefaultCompositorParticleRegions(),
poolSize: 160,
projectionScaleRatio: 1,
});

this.particleEmitters.push({
kind: 'rocketFire',
x: this.shipX,
y: this.shipY + 58,
rateMs: 24,
burstSize: 1,
accumulatorMs: 0,
});

Hs2dLevelScene.updateParticles automatically calls particles.update(deltaMs, this.particleEmitters, activeCamera) when this.particles and a camera are available.

Update, Render, And Compose Behavior

PhaseBehavior
BuildAllocates particle sprite handles in a host sprite layer compositor and hides them.
Emitter updateAccumulates emitter time and emits bursts when accumulatorMs >= rateMs.
Particle updateAdvances age and velocity, changes frame within the particle atlas, moves sprites relative to camera, and deactivates expired particles.
Render/composeThe host sprite layer renders and composes the particle sprites. Hs2dParticleLayer is not itself a GameSceneLayer.

The layer adapts camera scale through projectionScaleRatio, similar to sprite layers.

The default atlas has 16 frames: sparkle 0-3, fire/explosion 4-7, laser/missile 8-11, and dust 12-15.

Performance Notes

  • Keep poolSize fixed and measured.
  • When the pool is full, new emissions are dropped rather than allocating more sprites.
  • Reset optional telemetry counters once per stats window with resetCounters. onStatsWindow() is compiled out when __TELEMETRY__ is disabled, so required state resets belong elsewhere.
  • Use clear() on restart or scene reset to hide all active particles.
  • Keep emitter arrays stable. Mutate emitter positions rather than replacing arrays in the frame loop.
  • Use particles for short effects only; use sprite pools for gameplay collisions and ownership.

Code Sample

protected override updateParticles(deltaMs: number): void {
Hs2dParticleLayer.updateRocketEmitters(this.particleEmitters, {
x: this.shipX,
y: this.shipY,
});

super.updateParticles(deltaMs);
this.activeParticles = this.particles?.getStats().activeParticles ?? 0;
}

private emitExplosion(x: number, y: number): void {
this.particles?.emitForEmitter(
{ kind: 'explosion', x, y, rateMs: 1, burstSize: 12, accumulatorMs: 1 },
this.activeCamera,
);
}

Source References

SourceWhy it matters
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dParticleLayer.tsHs2d particle wrapper, projection scale, update, emit, clear, counters, and stats.
../games/hosanna-ui/src/hosanna-game/particles/CompositorParticleSystem.tsFixed particle pool, built-in emitters, emission behavior, movement, frame updates, and offscreen parking.
../games/hosanna-ui/src/hosanna-game/hosanna2d/Hs2dWorld.tsaddParticleLayer creation and particle stats in world snapshots.
../games/hosanna-ui/src/hosanna-game/hosanna2d/game/Hs2dLevelScene.tsScene-level particleEmitters array and updateParticles hook.
../hosanna-ui-game-samples-public/src/hosanna-game-examples/native-shoot-em-up/VerticalShooterLevelScene.tsGameplay particle creation, rocket emitter updates, one-shot bursts, and stats.
../hosanna-ui-game-samples-public/src/hosanna-game-examples/diagnostics/ParticleRigController.tsStandalone particle diagnostic using CompositorParticleSystem directly.
Talk to us