Falling Particles (d3.js)

HTML

<script src="https://d3js.org/d3.v3.min.js"></script>
<button id="start">Start</button>
<div id="container"></div>

CSS

circle.particle {
    fill: white;
    stroke: none;
}
svg {
    background-color: black;
}

JavaScript

/*
/ README
*/

// Basic control variables
var gridSize = 400;     // The square size in pixels of the 2-d world
var numParticles = 100;
var epochTarget = 10;
var epochActual = 0;
var counter = 0;

var getXSpeed = function(){
    // Returns a number from -25 to -1 or 1 to 25
    return (2);
};

var getYSpeed = function(){
    // Returns a number from 25-100
    return (1);
};

/*
*/
var particles = [];
for(var i=0; i<numParticles; i++){
    particles.push({
        x: Math.floor(Math.random() * gridSize),
        y: 0,
        r: 3,
        key: counter++,
        vx: getXSpeed(),
        vy: getYSpeed()
    });
}

// Create the initial structure of the game board (using SVG rectangles)
var svg = d3.select("#container").append("svg")
    .attr("height", gridSize)
    .attr("width", gridSize)
    .append("g");

// Redraw function is responsible for updating the state of the dom
var redraw = function(elapsed){
    // Bind the data to the particles
    var particle = svg.selectAll("circle.particle").data(particles, function(d) { return d.key; } );

    // Update
    particle
        .attr("cx", function(d) { return d.x; } )
        .attr("cy", function(d) { return d.y; } );

    // Enter
    particle.enter().append("circle")
        .attr("class", "particle")
        .attr("cx", function(d) { return d.x; } )
        .attr("cy", function(d) { return d.y; } )
        .attr("r", function(d) { return d.r; });
    
    particle.exit().remove();
};

/*
*/
var update = function(elapsed){
    for(var j=0; j<particles.length; j++){
        var particle = particles[j];
        
        particle.x = particle.x + (elapsed/1000) * particle.vx;
        particle.y = particle.y + (elapsed/1000) * particle.vy;
        
        if(particle.x < -10) { particle.x = gridSize - 1; }
        if(particle.x > gridSize + 10) { particle.x = 0; }

        // Particle is done, so recreate it
        if(particle.y > gridSize - 1) { 
            particle.x = Math.floor(Math.random() * gridSize);
...