GUIDE 05 · EFFECTS

Give motion
weight and sound.

Particles and audio are independent runtime systems. Connect them to animation, physics, or gameplay events without coupling them to one renderer or mixer.

Create a pooled system

particles.dartDART
final sparks = GlintParticleSystem(
  const GlintParticleConfig(
    maxParticles: 2000,
    emissionRate: 180,
    lifetime: GlintDoubleRange(.25, 1.1),
    startSpeed: GlintDoubleRange(2, 8),
    shape: GlintConeParticleShape(
      angle: .35,
      baseRadius: .1,
    ),
    gravity: Vector3(0, -9.81, 0),
    blendMode: GlintParticleBlendMode.additive,
  ),
  seed: 42,
);

Particles live in dense reusable typed arrays. Emission and simulation are deterministic for the same seed and fixed update sequence.

Shape emission and appearance

Emitters

Point, box, sphere, and cone shapes plus continuous rates, manual emission, and scheduled bursts.

Motion

Speed ranges, gravity, drag, procedural noise, local or world simulation, and prewarming.

Appearance

Size curves, color/alpha gradients, rotation, alpha or additive blending, sorting, textures, and sprite sheets.

Events

World-space spawn, collision, and death signals for gameplay or secondary effects.

frame.dartDART
sparks.update(dt);
return GlintGameFrame(
  camera: camera,
  instances: instances,
  particles: [sparks.renderBatch],
);

Collide through the physics contract

particle_collision.dartDART
sparks.update(
  fixedDt,
  collisions: GlintPhysicsParticleCollisionResolver(physics),
);

The adapter traces particle movement with backend-neutral queries, then applies the configured response. Local-space systems still query and emit events in world space.

Add the SoLoud backend

TerminalSHELL
flutter pub add glint_soloud
audio_setup.dartDART
final audio = GlintAudioEngine(
  backend: GlintSoLoudAudioBackend(),
);
await audio.initialize(
  config: const GlintAudioConfig(maxActiveVoices: 96),
);

final effects = audio.createBus('effects');
final impact = await audio.load(
  const GlintAudioSource.asset('assets/audio/impact.ogg'),
);

The core contract supports cached asset, file, bounded network, and encoded-memory sources; buses; voice controls; loading policy; and listener/source state. Apps without glint_soloud do not inherit its native build.

Update the listener and moving voices

spatial_audio.dartDART
audio.listener = GlintAudioListener(
  position: camera.position,
  forward: camera.target - camera.position,
  velocity: cameraVelocity,
);

final voice = audio.playSpatial(
  impact,
  hit.position,
  bus: effects,
  options: const GlintSpatialAudioOptions(
    minimumDistance: 1,
    maximumDistance: 80,
    dopplerFactor: 1,
  ),
);
voice.setSpatialState(car.position, velocity: car.linearVelocity);

Distance attenuation, panning, and Doppler depend on consistent world units and meaningful velocity. Update long-lived moving voices every simulation frame.

Choose the right loading mode

Memory

Short effects and anything latency-sensitive. Decode once and reuse the cached clip.

Stream

Music and long ambience. Protect important music voices from ordinary voice-limit stealing.

Buses

Separate music, effects, UI, ambience, and dialogue for independent volume and pause policy.

Dispose

Stop voices, release clips and buses, then dispose the engine when the owning application scope ends.

BUILD

The host needs CMake to build flutter_soloud. On macOS, install it with brew install cmake.