import { Vector } from "../components/vector" ; import { settings } from "../settings" ; import { evaluateVariation } from "../systems/variation" ; import { overrideDefaults } from "../util/config" ; import { EmissionOptions , EmitterOptions , RenderOptions , getDefaultEmissionOptions , getDefaultEmitterOptions , getDefaultRendererOptions , } from "./options" ; import { Particle } from "./particle" ; /**
 * Defines the set of options that can be used when creating a new emitter.
 */ export interface EmitterConstructionOptions { emitterOptions ? : Partial < EmitterOptions > ; emissionOptions ? : Partial < EmissionOptions > ; rendererOptions ? : Partial < RenderOptions > ; } see Particle see ParticleModifierModule export class Emitter { /**
     * The particles currently contained within the system.
     */ public readonly particles : Particle [ ] = [ ] ; /**
     * The main options of the emitter.
     */ public readonly options : EmitterOptions ; /**
     * The emission options of the emitter.
     */ public readonly emission : EmissionOptions ; /**
     * The renderer options of the emitter.
     */ public readonly renderer : RenderOptions ; private currentLoop = 0 ; private durationTimer = 0 ; private emissionTimer = 0 ; private attemptedBurstIndices : number [ ] = [ ] ; /**
     * Checks if the emitter is already expired and can be removed.
     * Expired emitters do not emit new particles.
     */ public get isExpired ( ) : boolean { return ( this . options . loops >= 0 && this . currentLoop >= this . options . loops ) ; } /**
     * Checks if the emitter can safely be removed.
     * This is true if no more particles are active.
     */ public get canRemove ( ) : boolean { return this . particles . length === 0 ; } /**
     * Creates a new emitter, using default options.
     */ constructor ( options ? ) { this . options = overrideDefaults ( getDefaultEmitterOptions ( ) , options ?. emitterOptions ) ; this . emission = overrideDefaults ( getDefaultEmissionOptions ( ) , options ?. emissionOptions ) ; this . renderer = overrideDefaults ( getDefaultRendererOptions ( ) , options ?. rendererOptions ) ; } returns public clearParticles ( ) { return this . particles . splice ( 0 ) . length ; } remarks param delta public tick ( delta ) { if ( ! this . isExpired ) { this . durationTimer += delta ; if ( this . durationTimer >= this . options . duration ) { this . currentLoop ++ ; this . durationTimer = 0 ; this . attemptedBurstIndices = [ ] ; } if ( ! this . isExpired ) { let burstIndex = 0 ; for ( const burst of this . emission . bursts ) { if ( burst . time <= this . durationTimer ) { if ( ! this . attemptedBurstIndices . includes ( burstIndex ) ) { const count = evaluateVariation ( burst . count ) ; for ( let i = 0 ; i < count ; i ++ ) { this . emitParticle ( ) ; } this . attemptedBurstIndices . push ( burstIndex ) ; } } burstIndex ++ ; } this . emissionTimer += delta ; const delay = 1 / this . emission . rate ; while ( this . emissionTimer > delay ) { this . emissionTimer -= delay ; this . emitParticle ( ) ; } } } for ( let i = this . particles . length - 1 ; i >= 0 ; i -- ) { const particle = this . particles [ i ] ; this . tickParticle ( particle , delta ) ; if ( this . options . despawningRules . some ( ( rule ) => rule ( particle ) ) ) { this . particles . splice ( i , 1 ) ; } } } remarks param particle param delta private tickParticle ( particle , delta ) { particle . lifetime -= delta ; if ( this . options . useGravity ) { particle . velocity = particle . velocity . add ( Vector . up . scale ( settings . gravity * delta ) ) ; } particle . location = particle . location . add ( particle . velocity . scale ( delta ) ) ; for ( const moduleFunction of this . options . modules ) { moduleFunction ( particle ) ; } } /**
     * Emits a particle using the registered settings.
     * Also may despawn a particle if the maximum number of particles is exceeded.
     */ private emitParticle ( ) { const particle = new Particle ( { location : this . emission . sourceSampler ( ) , lifetime : evaluateVariation ( this . emission . initialLifetime ) , velocity : Vector . from2dAngle ( evaluateVariation ( this . emission . angle ) ) . scale ( evaluateVariation ( this . emission . initialSpeed ) ) , size : evaluateVariation ( this . emission . initialSize ) , rotation : evaluateVariation ( this . emission . initialRotation ) , color : evaluateVariation ( this . emission . initialColor ) , } ) ; this . particles . push ( particle ) ; if ( this . particles . length > this . options . maxParticles ) { this . particles . shift ( ) ; } return particle ; } }