Fire ready-made effects in one call, or shape your own particles with world.burst.
Import effects and call one function per event; each layers a few bursts (big slow pieces, small fast ones, a glow, lingering puffs) that move, fade and clean up in Rust. Particles advance with the world, so they pause with the game.
Every particle takes a world slot, so size the World's capacity for the busiest moment. Effects throw on a disposed world: check world.isDisposed in callbacks that can run late.
| Call | Use it for |
|---|---|
| effects.confetti(world, options) | Wins and level-ups: tumbling paper, glints, a pop of light. |
| effects.sparkle(world, options) | Pickups and perfect moves: bright beads and glints. |
| effects.shatter(world, options) | Bricks, crates, glass: chunks, crumbs, a glow and dust. |
| effects.splash(world, options) | Water, juice, paint: droplets and mist. |
| effects.sparks(world, options) | Scrapes, strikes, electricity: hot streaks and beads. |
| effects.explosion(world, options) | Flash, fireball cooling to smoke, embers and optional debris. |
| effects.dust(world, DustOptions) | Soft swelling puffs: landing dust, sand, steam. Returns the count. |
| effects.flash(world, FlashOptions) | One swelling glow: hits, strikes, muzzle flashes. Returns the count. |
| effects.pop(world, entity, PopOptions) | A cleared piece swells, flashes white and shrinks away. Returns a Promise. |
| effects.hot(color, peak = 2.2, alpha?) | The same hue made self-lit, for glows. |
| effects.pale(color, t, alpha?) | The color moved part way (t, 0..1) toward white. |
| effects.POP_TIME | Default pop duration: 0.5 seconds. |
Celebrate a win and reward a pickup
React and React Native · shared engine API
import { effects, type Vec3, type World } from "@nayan-ui/engine";export function celebrate(world: World, position: Vec3) {effects.confetti(world, {position, colors: ["#FF4D4D", "#FFD933", "#3399FF"],size: 0.12, speed: 6, count: 40, lifetime: 1.2, gravity: -6,});}export function collect(world: World, position: Vec3) {effects.sparkle(world, { position, colors: "#FFD933", size: 0.08, speed: 3, count: 14, lifetime: 0.6 });}
confetti, sparkle, shatter, splash, sparks and explosion share EffectOptions; position, colors, size, speed, count and lifetime are required, except colors for explosion. Sizes are world units, speeds units per second and times seconds.
| Option | Meaning |
|---|---|
| position | Where the effect starts. |
| colors | One CSS color or tuple, or several picked at random. |
| size / speed | Typical particle size; top speed. |
| count | About how many particles; a few extra go to the glow and puffs. |
| lifetime | Seconds. |
| gravity | Vertical acceleration; negative falls. Default 0. |
| direction / spread | Main direction (default up); cone half-angle (default π, all directions). |
| flash | A brief glow at the source. Default true. |
| shatter: mesh / dust | Chunk shape (default "cube"); dust: false skips the puff. |
| explosion: debris / smoke | Colors of flying chunks; smoke color. size is the fireball's puff size. |
Break, splash, scrape and blow up
React and React Native · shared engine API
import { effects, type EffectOptions, type Vec3, type World } from "@nayan-ui/engine";const water: Omit<EffectOptions, "position"> = {colors: "rgba(77, 153, 255, 0.9)", size: 0.1, speed: 4, count: 24, lifetime: 0.8, gravity: -9.8,};export const splashAt = (world: World, position: Vec3) => effects.splash(world, { ...water, position });export function breakCrate(world: World, position: Vec3) {effects.shatter(world, { position, colors: ["#8B5A2B", "#6B4220"], size: 0.2, speed: 5, count: 16,lifetime: 0.7, gravity: -9.8, mesh: "cube" });}export function scrape(world: World, position: Vec3, away: Vec3) {effects.sparks(world, { position, colors: "orange", size: 0.05, speed: 8, count: 20, lifetime: 0.4,direction: away, spread: 0.5, gravity: -6 });}export function blowUp(world: World, position: Vec3) {effects.explosion(world, { position, size: 0.6, speed: 6, count: 40, lifetime: 1,debris: ["#4D4D52"], smoke: "rgba(50, 50, 50, 0.6)" });}
effects.dust makes soft puffs that swell and fade; gravity defaults to 0 so dust hangs, and positive values rise like smoke. effects.flash draws one glow at a point; channels above 1 glow, most easily via effects.hot(color).
| Option | Meaning |
|---|---|
| position | Required by both. |
| dust: color | Start color (alpha is thickness), or several. Required. |
| dust: size / speed / count / lifetime | Required: puff size, top speed, puffs, seconds. |
| dust: direction / spread / gravity | Default up, π and 0 (positive rises). |
| dust: endSize / endColor | Growth by the end (default 2); end color (default: faded). |
| dust: mesh | Default "puff" (blended); "flame" adds light. |
| flash: color / size | Required. Channels above 1 glow. |
| flash: lifetime / endSize | Defaults 0.22 seconds and 2.2. |
| flash: endColor | Default: color faded to transparent. |
| flash: mesh | Default "flame" (additive); "sphere" or "puff" for solid or soft. |
| flash: count / speed | Glows drawn (default 1), scattered when speed > 0 (default 0). |
Landing dust, a hit flash and steam
React and React Native · shared engine API
import { effects, type Vec3, type World } from "@nayan-ui/engine";export function landed(world: World, feet: Vec3) {effects.dust(world, { position: feet, color: "rgba(204, 191, 166, 0.6)", size: 0.3, speed: 1.5, count: 6, lifetime: 0.5 });}export function hit(world: World, at: Vec3) {effects.flash(world, { position: at, color: effects.hot("#FF8000"), size: 0.8 });}export function steam(world: World, vent: Vec3) {effects.dust(world, { position: vent, color: effects.pale("#99B3CC", 0.6, 0.4), size: 0.4, speed: 1,count: 8, lifetime: 1.5, gravity: 1, endSize: 3 });}
effects.pop(world, entity, options) swells a cleared, matched or collected piece, flashes it white, settles it and shrinks it to nothing, stopping any animation it had. It resolves when the piece is gone; despawn it then, with no guard needed since despawn is safe after dispose.
| PopOptions | Meaning |
|---|---|
| scale | Its rest scale, a number or Vec3. Required. |
| color | Rest color to return to after the white flash; omit to skip it. |
| flash | Child entities (white at rest) to flash as well. |
| delay | Seconds before it starts. Default 0. |
| duration | Seconds. Default effects.POP_TIME (0.5). |
Clear matched pieces in a wave
React and React Native · shared engine API
import { effects, type ColorInput, type Entity, type World } from "@nayan-ui/engine";export async function clearPieces(world: World, pieces: readonly Entity[], color: ColorInput) {await Promise.all(pieces.map((piece, i) =>effects.pop(world, piece, { scale: 1, color, delay: i * 0.05 }).then(() => world.despawn(piece))));}
Use world.burst(options) only when you need one plain layer under exact control; it spawns up to count particles in one native call and returns how many fit. Particles advance and expire with world.update.
The "puff" mesh is a soft camera-facing sprite that alpha-blends, and "flame" is the same sprite added to the scene, so overlaps build a bright core. Neither is solid or a light source, and shapeGeometry can't build them.
| BurstOptions | Meaning |
|---|---|
| position | Origin. Required. |
| count | Particles. Default 16. |
| direction / spread | Main direction, default up; cone half-angle, default π. |
| mesh | Built-in shape or Model. Default "cube". |
| size / speed / lifetime | Defaults 0.15 units, 5 units per second, 0.8 seconds. |
| gravity | Vertical acceleration. Default -9.81; 0 floats. |
| color | One color, or up to four picked per particle. Default white. |
| endSize | End size as a multiple of the start; above 1 grows. Default 1. |
| endColor | Color reached by the end; alpha below 1 fades out. |
Smoke and sparks
React and React Native · shared engine API
import type { Vec3, World } from "@nayan-ui/engine";export function smokeAndSparks(world: World, position: Vec3) {world.burst({ position, mesh: "puff", count: 18, color: "rgba(128, 128, 128, 0.5)", size: 0.3,speed: 2, gravity: 0, lifetime: 1.5, endSize: 4, endColor: "rgba(50, 50, 50, 0)" });// Glowing colors need channels above 1, so these are 0..1+ tuples.return world.burst({ position, mesh: "flame", count: 28, direction: [0, 1, 0], spread: Math.PI / 2,color: [[2, 1.2, 0.2], [2, 0.4, 0.1]], speed: 7, lifetime: 0.6, endSize: 0.1 });}