import {compose, Property} from '@avocado/core'; import {Trait} from '@avocado/entity'; import {Ticker} from '@avocado/timing'; const decorate = compose( ); export class Emitter extends decorate(Trait) { constructor(entity, params, state) { super(entity, params, state); this.emitters = {}; if (AVOCADO_CLIENT) { this.ticker = new Ticker(1 / 60); this.ticker.on('tick', this.onTick, this); } } static type() { return 'emitter'; } 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); } onTick(elapsed) { for (const key in this.emitters) { const emitter = this.emitters[key]; emitter.tick(elapsed); } } updateFrequency() { const particleCount = this.constructor.particleCount(); const updatesPerSecond = Math.max(15, (60 - (particleCount / 10))); this.ticker.frequency = 1 / updatesPerSecond; } hooks() { const hooks = {}; if (AVOCADO_CLIENT) { hooks.afterDestructionTickers = () => { return (elapsed) => { for (const key in this.emitters) { const emitter = this.emitters[key]; this.ticker.tick(elapsed); if (!emitter.hasParticles()) { this.ticker.off('tick', this.onTick); emitter.destroy(); this.constructor.removeEmitter(emitter); delete this.emitters[key]; } } return 0 === Object.keys(this.emitters).length; }; }; } return hooks; } methods() { return { addEmitter: (key, emitter) => { if (AVOCADO_CLIENT) { this.emitters[key] = emitter; this.constructor.addEmitter(emitter); } }, addEmitterRenderer: (key, renderer) => { if (AVOCADO_CLIENT) { if (!this.emitters[key]) { return; } this.emitters[key].addRenderer(renderer); } }, emitParticle: (key, ...args) => { if (!this.emitters[key]) { return; } this.emitters[key].emit(...args); }, } } tick(elapsed) { if (AVOCADO_CLIENT) { this.ticker.tick(elapsed); } } }