The pack
gpuParticles
function gpuParticles(): Pack<{ gpuParticles: GpuParticlesApi }>
The GPU particles pack: pools of up to two million particles simulated on the GPU each frame (particles-gpu.sim,
before sprites) and drawn by a registered drawer in the emitter object's sorted place — a screen of weather
behind the world, a nova over it. Forces as data (accel, drag, curl noise, attract, vortex, orbit, wind), a
wrap box for weather over an unbounded world, four-stop colour ramps, fade modes, twinkle, stretch. Additive by
default (an unsorted pool is only order-independent additive). WebGPU compute and WebGL2 transform feedback keep the pools GPU-resident; headless the emitters exist and draw nothing.
Constants
GPU_DRAWER_ID
const GPU_DRAWER_ID: 2
The id this pack registers its drawer under.
Types
GpuEmitterApi
interface GpuEmitterApi
The gpu sub-object on a GPU emitter handle.
rate: number— Particles per second, live.burst(count: number): void— Queue a one-shot spawn ofcountthis frame.readonly capacity: number— The pool size.readonly alive: number— An estimate of the live count (spawned within the longest lifetime), updated each step.readonly config: GpuEmitterConfig— The live config; mutate ranges andforcesin place.paused: boolean— Hold the simulation.
GpuEmitterConfig
interface GpuEmitterConfig
The GPU emitter config. Ranges are [min, max]; a single number is fixed. Degrees, world units, seconds.
x?: number— World x. Default 0.y?: number— World y. Default 0.layer?: string— The layer.z?: number— Depth in the layer. Default 0.follow?: Handle— Follow this object.offset?: { x?: number; y?: number }— Offset from it.capacity?: number— Pool size: the most alive at once; a RING — past it the oldest are recycled. 64..2M. Default 65536.rate?: number— Particles per second. Default 0 (bursts only).emitZone?: GpuZone— Born here. Default point.angle?: number | [number, number]— Launch direction range, degrees. Default [0, 360].radial?: boolean— Velocity points away from the emitter (for shells and novas; overridesangle). Default false.speed?: number | [number, number]— Launch speed. Default [40, 80].lifespan?: number | [number, number]— Lifetime, seconds. Default [1, 2].size?: number | [number, number]— Size, world units (the frame's longer side). Default [4, 8].endSize?: number— Size at death as a fraction of the birth size: 0 shrinks to nothing, 1 constant, above 1 grows. Default 0.fade?: boolean | number— Alpha over life: true fades linearly over the whole life; false never; a number fades only over that final fraction (0.2 = the last 20%). Default true.color?: string | ReadonlyArray<string>— Colour over life: one hex, or up to four stops. Default white.alpha?: number— Alpha multiplier. Default 1.twinkle?: number— Per-particle brightness flicker 0..1. Default 0.rotate?: number | [number, number]— Visual rotation range at birth, degrees. Default 0.spin?: number | [number, number]— Spin range, degrees/s. Default 0.alignToVelocity?: boolean— Point the frame along the velocity. Default false.stretch?: number— Elongate along the velocity by speed × this / 100. Default 0.gravityX?: number— Gravity x, units/s². Default 0.gravityY?: number— Gravity y. Default 0.drag?: number— Velocity damping per second. Default 0.forces?: GpuForce[]— Forces, as data; mutate the list live. At most eight.wrap?: { w: number; h: number }— Fold positions into a box of this size centred on the emitter (weather over an unbounded world: move the emitter with the camera).frame?: string | number— The atlas frame (a key or index). Default the white pixel.blend?: 'add' | 'normal'— 'add' (default — an unsorted pool is only order-independent additive) or 'normal'.seed?: number— Seed for the spawn hash. Default from the kernel rng.
GpuEmitterHandle
type GpuEmitterHandle = Handle & { gpu: GpuEmitterApi }
A GPU emitter is a roster handle with a gpu sub-object.
GpuForce
type GpuForce = | { kind: 'accel'; x?: number; y?: number } | { kind: 'drag'; amount: number } | { kind: 'curl'; strength: number; scale?: number; speed?: number } | { kind: 'attract'; x: number; y: number; strength: number; radius?: number } | { kind: 'vortex'; x: number; y: number; strength: number; radius?: number } | { kind: 'orbit'; x: number; y: number; strength: number; radius: number; spring?: number } | { kind: 'wind'; x: number; y: number; gust?: number; gustSpeed?: number }
A force on a GPU emitter, as data. Positions are relative to the emitter. At most eight.
GpuParticlesApi
interface GpuParticlesApi
game.gpuParticles.
emitter(cfg: GpuEmitterConfig): GpuEmitterHandle— Spawn a GPU emitter object. Throws on more than eight forces or an unknown frame.readonly emitters: ReadonlyArray<GpuEmitterHandle>— Live emitters.readonly count: number— Estimated live particles across every emitter.readonly ready: boolean— True when the backend has a device and the pipelines exist.
GpuZone
type GpuZone = { kind: 'point' } | { kind: 'circle'; r: number; inner?: number } | { kind: 'rect'; w: number; h: number } | { kind: 'ring'; r: number; width?: number }
Where GPU particles are born, relative to the emitter.


