Basic particle system

Work in progress

by Nick Hulea

HTML

<canvas id="demo" width=450 height=500></canvas>
<div class="cont">
    <button id="start">Start emitter</button>
    <br>
    <br> <span>Emitter settings</span>

    <div>Limit:
        <br />
        <input id="limit" type=range min=1 max=1000 value=1000 />
    </div>
    <div>Spawn angle:
        <br />
        <input id="spawn" type=range min=0 max=360 value=6 />
    </div>
    <div>Angle offset:
        <br />
        <input id="angle" type=range min=0 max=360 value=267 />
    </div>
    <div>Gravity:
        <br />
        <input id="gravity" type=range min=0 max=100 value=7 />
    </div> <span>Particle settings</span>

    <div>Weight:
        <br />
        <input id="weight" type=range min=0 max=50 value=4 />
    </div>
    <div>Min. velocity:
        <br />
        <input id="velmin" type=range min=1 max=10 value=3 />
    </div>
    <div>Max. velocity:
        <br />
        <input id="velmax" type=range min=1 max=10 value=5 />
    </div>
    <div>Life:
        <br />
        <input id="life" type=range min=-1 max=1000 value=-1 />
    </div>
</div>

CSS

body {
    margin:0;
    background:#999;
    font:12px sans-serif;
}
button {
    float:left;
    clear:both;
}
#demo {
    width:450px;
    float:left;
    cursor:crosshair;
    background:#333;
}
.cont {
    width:150px;
    margin:10px;
    float:left;
}
div {
    margin:12px 0;
}
span {
    font-weight:strong;
    font-size:14px;
}

JavaScript

replaceInputRange();
/**
 *    Basic particle system version 1.0 ALPHA
 *    (work in progress)
 *
 *    By Ken Fyrstenberg Nilsen
 *    http://abdiassoftware.com/
 *
 *    License: CC3.0-attribution
 */

/// x, y, gravity, spawn angle, angle offset, limit
/// angles in radians
function Emitter(x, y, g, a, ao, limit) {

    var me = this,
        particles = [];

    this.limit = limit || 1000;
    this.x = x;
    this.y = y;
    this.gravity = g || 0;
    this.angle = a || 2 * Math.PI;
    this.angleOffset = ao || 0;
    this.count = 0;

    this.add = function (v, w, life) {

        var p = new Particle();
        p.x = me.x;
        p.y = me.y;
        p.life = life || -1;
        p.velocity = v;
        p.weight = w * (me.gravity / 1000);
        p.angle = getAngle();
        p.init();

        particles.push(p);

        if (particles.length > me.limit) {
            particles.splice(0, (particles.length - me.limit));
        }
        me.count = particles.length;
    }

    this.update = function (ctx) {

        var i = 0,
            p,
            live = [];

        for (; p = particles[i]; i++) {
            p.update();
            if (p.life !== 0) live.push(p);
            ctx.fillRect(p.x, p.y, 2, 2);
        }

        particles = live;
        me.count = particles.length;
    }

    function getAngle() {
        return me.angle * Math.random() + me.angleOffset;
    }
}

/// velocity, weight
function Particle() {}
Particle.prototype.update = function () {
    this.stepY += this.weight;
    this.x += this.stepX;
    this.y += this.stepY
    if (this.life > -1) this.life--;
}
Particle.prototype.init = function () {
    this.stepX = this.velocity * Math.cos(this.angle);
    this.stepY = this.velocity * Math.sin(this.angle);
}
Particle.prototype.life = 1000;
Particle.prototype.x = 0;
Particle.prototype.y = 0;
Particle.prototype.stepX = 0;
Particle.prototype.stepY = 0;
Particle.prototype.velocity = 0;
Particle.prototype.weight =...