Source: particles/particle_set.js

/* 
 * File: particle_set.js
 * a set of Particles
 * 
 * Subclass of GameObjectSet: 
 *     GameObjectSet: a set of objects that support: update() and draw() functions
 *                     Particle satisfies!
 */
"use strict";

import * as glSys from "../core/gl.js";
import GameObjectSet from "../game_objects/game_object_set.js";
import ParticleEmitter from "./particle_emitter.js";

class ParticleSet extends GameObjectSet {

    /**
     * @classdesc Support a list of Particles and ParticleEmitters
     * <p> Found in Chapter 10, page 652 of the textbook</p>
     * 
     * Examples:
     * {@link https://mylesacd.github.io/build-your-own-2d-game-engine-2e-doc/BookSourceCode/chapter10/10.1.particles/index.html 10.1 Particles}
     * {@link https://mylesacd.github.io/build-your-own-2d-game-engine-2e-doc/BookSourceCode/chapter10/10.2.particle_collisions/index.html 10.2 Particle Collision}
     * {@link https://mylesacd.github.io/build-your-own-2d-game-engine-2e-doc/BookSourceCode/chapter10/10.3.particle_emitters/index.html 10.3 Particle Emitters}
     * 
     * @extends GameObjectSet
     * @returns {ParticleSet} a new ParticleSet instance
     */
    constructor() {
        super();
        this.mEmitterSet = [];
    }

    /**
     * Draw the Particles in this ParticleSet using additive blending
     * @method
     * @param {Camera} aCamera - the Camera to draw to
     */
    draw(aCamera) {
        let gl = glSys.get();
        gl.blendFunc(gl.ONE, gl.ONE);  // for additive blending!
        super.draw(aCamera);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); // restore alpha blending
    }

    /**
     * Add a new ParticleEmitter to the lsit
     * @method
     * @param {float} x - X world coordinate position for this Emitter
     * @param {float} y - Y world coordinate position for this Emitter
     * @param {int} n - number of Particles to emit
     * @param {function} func - function for the emitter to use for Particle Generation
     */
    addEmitterAt(x, y, n, func) {
        let e = new ParticleEmitter(x, y, n, func);
        this.mEmitterSet.push(e);
    }

    /**
     * Draw the markers of the Particles in this ParticleSet
     * @method
     * @param {Camera} aCamera - the Camera to draw to
     */
    drawMarkers(aCamera) {
        let i;
        for (i = 0; i < this.mSet.length; i++) {
            this.mSet[i].drawMarker(aCamera);
        }
    }

    /**
     * Emit Particles and prune expired objects
     * @method
     */
    update() {
        super.update();
        // Cleanup Particles
        let i, obj;
        for (i = 0; i < this.size(); i++) {
            obj = this.getObjectAt(i);
            if (obj.hasExpired()) {
                this.removeFromSet(obj);
            }
        }

        // Emit new particles
        for (i = 0; i < this.mEmitterSet.length; i++) {
            let e = this.mEmitterSet[i];
            e.emitParticles(this);
            if (e.expired()) {  // delete the emitter when done
                this.mEmitterSet.splice(i, 1);
            }
        }
    }
}

export default ParticleSet;