Particles - Rain

This is a RW-accurate particle dropper. Particles have a random mass from 1 to 100 kg. This is denoted by their size. Since mass has no effect on gravitational pull, they all fall at the same rate. On death, the particles automatically respawn in a random position in the sky. This gives the illusion after a while of rain, since they all start at different times and different positions, though they all still fall at the speed of gravity, as it were.

by djwelsh

HTML

<canvas id="c" width="400" height="400"></canvas>

CSS

canvas {
    width: 400px;
    height: 400px;
    outline: 1px solid #ccc;
}

JavaScript

var BOX_WIDTH = 380;
var BOX_HEIGHT = 380;
var g = 9.81; // m/s^2
var wind = 12 * (Math.random() - 0.5);

LEFT_BOUND = 0;
RIGHT_BOUND = 400;
LOWER_BOUND = 0;
UPPER_BOUND = 390;

var particles = [];

for (var i = 0; i < 100; i++) {
    particles.push(new Particle(
        {
            x : 10 + 380 * Math.random(),
            y : 10 + 100 * Math.random(),
            vx : 0,
            vy : 0,
            mass : Math.random() * 100
        }
    ));
}
var ctx = (document.getElementById('c')).getContext('2d')

var lastTime = (new Date()).getTime();
var thisTime = 0;
var timeElapsed = 0;
var timeInterval = 1000; //1 second

function update () {
    
	thisTime = (new Date()).getTime();
    timeElapsed = thisTime - lastTime;
    
    for  (var i = 0; i < 100; i++) {
        particles[i].update(timeElapsed / 1000);
    }
    lastTime = thisTime;
    
    setTimeout(update, 1000 / 60);
}

function draw () {
    
    ctx.clearRect(0, 0, 400, 400);
//    ctx.save();
//    ctx.fillStyle = "rgba(255, 255, 255, 0.05)";
//    ctx.fillRect(0, 0, 400, 400);
//    ctx.restore();
    
    ctx.save();
    ctx.fillStyle = "black";
	ctx.fillRect(0, 390, 400, 10);
	ctx.restore();
    
    for  (var i = 0; i < 100; i++) {
    	particles[i].draw(ctx);
    }
    
    //Draw ruler
    ctx.save()
    ctx.beginPath();
    
    ctx.moveTo(10, 90);
    ctx.lineTo(10, 390);
    
    ctx.moveTo(10, 90);
    ctx.lineTo(15, 90);
    ctx.moveTo(10, 190);
    ctx.lineTo(15, 190);
    ctx.moveTo(10, 290);
    ctx.lineTo(15, 290);
    ctx.moveTo(10, 390);
    ctx.lineTo(15, 390);
    ctx.strokeStyle = "red";
    ctx.fillStyle = "red";
    ctx.stroke();
    ctx.textBaseline = "middle";
    ctx.fillText("300 m", 15, 90);
    ctx.fillText("200 m", 15, 190);
    ctx.fillText("100 m", 15, 290);
    ctx.fillText("0 m", 15, 390);
    ctx.restore();
    
    //Wind vector
    ctx.save()
    ctx.beginPath();
    
    ctx.strokeStyle = "blue";
    ctx.fillStyle = "blue";
    ctx.arc(200, 25, 5, 0, Math.PI *...