121 lines
2.7 KiB
JavaScript
121 lines
2.7 KiB
JavaScript
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);
|
|
}
|
|
}
|
|
|
|
}
|