import {compose} from '@avocado/core'; import {Trait} from '@avocado/entity'; import {Property} from '@avocado/mixins'; import {Ticker} from '@avocado/timing'; const decorate = compose( ) export class Emitter extends decorate(Trait) { initialize() { this.emitters = {}; this.ticker = new Ticker(1 / 10); this.ticker.on('tick', (elapsed) => { this.updateFrequency(); for (const key in this.emitters) { const emitter = this.emitters[key]; emitter.tick(elapsed); } }); } static addEmitter(emitter) { if (!this._emitters) { this._emitters = []; } this._emitters.push(emitter); } static particleCount() { let particleCount = 0; if (!this._emitters) { return particleCount; } for (let i = 0; i < this._emitters.length; i++) { const emitter = this._emitters[i]; particleCount += emitter.particleCount; } return particleCount; } static removeEmitter(emitter) { const index = this._emitters.indexOf(emitter); if (-1 === index) { return; } this._emitters.splice(index, 1); } updateFrequency() { const particleCount = this.constructor.particleCount(); const updatesPerSecond = Math.max(15, (60 - (particleCount / 10))); this.ticker.frequency = 1 / updatesPerSecond; } hooks() { return { afterDestructionTickers: () => { return (elapsed) => { for (const key in this.emitters) { const emitter = this.emitters[key]; this.ticker.tick(elapsed); if (!emitter.hasParticles()) { emitter.destroy(); delete this.emitters[key]; } } return 0 === Object.keys(this.emitters).length; }; }, } } methods() { return { addEmitter: (key, emitter) => { this.emitters[key] = emitter; this.constructor.addEmitter(emitter); }, addEmitterRenderer: (key, renderer) => { if (!this.emitters[key]) { return; } this.emitters[key].addRenderer(renderer); }, emitParticle: (key, ...args) => { if (!this.emitters[key]) { return; } this.emitters[key].emit(...args); }, } } renderTick(elapsed) { this.ticker.tick(elapsed); } }