pixijs / particle-emitter

A particle system for PixiJS
http://pixijs.io/particle-emitter/docs
MIT License
799 stars 127 forks source link

add ability to customize emitter by extend from Emitter class #107

Closed ilya-klindukhov closed 5 years ago

ilya-klindukhov commented 5 years ago

Hi.

I want to extend from Emitter class to add some additional logic. But I have some problems because init() and update() now - are big functions where parsing/prepare emitter/particle and than apply this changes. Override all this functions for add some code not good idea. So I added some protected function before apply changes to particle/emitter (applyAdditionalProperties() and initAdditional()). Also spawnType parsing logic moved to separate function to easy override it (to parseSpawnType()).

Github show crazy diff but in real only create 2 empty functions and move spawn parsing to separate function.

example: create new spawn type where particles spawn on rect borders and move out by normal: customEmitter

import {Emitter, EmitterConfig, OldEmitterConfig, Particle} from "pixi-particles";
import {Rectangle} from "../../../export";
import Point = PIXI.Point;

export class ExtendedEmitter extends Emitter {

    protected static helperPoint: Point = new Point();

    protected parseSpawnType(config: EmitterConfig | OldEmitterConfig): void {
        switch (config.spawnType) {
            case "rectNormal":
                this.spawnType = "rect";
                this._spawnFunc = this._spawnRectNormal;
                const spawnRect = config.spawnRect;
                this.spawnRect = new Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h);
                break;
            default:
                super.parseSpawnType(config);
        }
    }

    protected _spawnRectNormal(p: Particle, emitPosX: number, emitPosY: number): void {
        //place the particle at a random point in the rectangle borders
        const isHorizontalBorder: boolean = !!Math.round(Math.random());
        if (isHorizontalBorder) {
            const isTop: boolean = !!Math.round(Math.random());
            ExtendedEmitter.helperPoint.x = Math.random() * this.spawnRect.width + this.spawnRect.x;
            ExtendedEmitter.helperPoint.y = (isTop ? 0 : 1) * this.spawnRect.height + this.spawnRect.y;
            p.rotation = isTop ? 270 : 90;
        } else {
            const isLeft: boolean = !!Math.round(Math.random());
            ExtendedEmitter.helperPoint.x = (isLeft ? 0 : 1) * this.spawnRect.width + this.spawnRect.x;
            ExtendedEmitter.helperPoint.y = Math.random() * this.spawnRect.height + this.spawnRect.y;
            p.rotation = isLeft ? 180 : 0;
        }

        p.position.x = emitPosX + ExtendedEmitter.helperPoint.x;
        p.position.y = emitPosY + ExtendedEmitter.helperPoint.y;
    }
}
andrewstart commented 5 years ago

This looks good, thanks!

ilya-klindukhov commented 5 years ago

Glad to help.