Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                
              
            
!

CSS

              
                head, body{
            width:100%;
            height:100%;
            overflow: hidden;
            top:0;
            left:0;
            margin:0;
            padding:0;
            background-color: #000000;
        }
        
        canvas{
            margin: auto;
            position: absolute;
            top: 0; left: 0; bottom: 0; right: 0;

            /*border-radius: 100%;*/

            -ms-transform: rotate(45deg); /* IE 9 */
            -webkit-transform: rotate(45deg); /* Chrome, Safari, Opera */
            transform: rotate(45deg);
        }
              
            
!

JS

              
                


function lerp ( t, a, b ){ return a + t * ( b - a ); }
function norm( t, a, b ){return ( t - a ) / ( b - a );}
function map( t, a0, b0, a1, b1 ){ return lerp( norm( t, a0, b0 ), a1, b1 );}

var PI = Math.PI;
var PI2 = PI * 2;
var RAD = PI / 180;
var DEG = 180 / PI;


//raf: https://github.com/cagosta/requestAnimationFrame/blob/master/app/requestAnimationFrame.js
(function(global) {(function() {if (global.requestAnimationFrame) {return;} if (global.webkitRequestAnimationFrame) {global.requestAnimationFrame = global[ 'webkitRequestAnimationFrame' ]; global.cancelAnimationFrame = global[ 'webkitCancelAnimationFrame' ] || global[ 'webkitCancelRequestAnimationFrame' ];} var lastTime = 0; global.requestAnimationFrame = function(callback) {var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = global.setTimeout(function() {callback(currTime + timeToCall);}, timeToCall); lastTime = currTime + timeToCall; return id;}; global.cancelAnimationFrame = function(id) {clearTimeout(id);};})(); if (typeof define === 'function') {define(function() {return global.requestAnimationFrame;});}})(window);


var canvas = document.createElement( 'canvas' );
document.body.appendChild( canvas );
var w = canvas.width = window.innerWidth;
var h = canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");

//var imageData = ctx.getImageData( 0,0,w,h );
//var data = imageData.data;
//
//imageData.data = data;
//ctx.putImageData( imageData,0,0 );

//get/set pixel

function getPixel( data, width, x, y )
{
    var id = ~~( x + width * y ) * 4;
    var r = data[id];
    var g = data[id+1];
    var b = data[id+2];
    var a = data[id+3];
    //return {r:r, g:g, b:b, a:a };
    return [ r, g, b, a ];
}

function setPixel( data, width, x, y, r,g,b,a )
{
    var id = ( x + width * y ) * 4;
    data[id] = r;
    data[id+1] = g;
    data[id+2] = b;
    data[id+3] = a;
}
var Point = function() {
	function Point(x,y,z) {
	this.x = x || 0; this.y = y || 0; this.z = z || 0; 	
}	var _p = Point.prototype; _p.constructor = Point; return Point; 	
}();

Point.prototype = {
	draw: function (ctx, radius) {
	ctx.beginPath(); ctx.arc(this.x, this.y, radius || 1, 0, Math.PI * 2); ctx.stroke(); 	
}, copy: function (other) {
	this.x = other.x; this.y = other.y; return this; 	
}, clone: function () {
	return new Point( this.x, this.y ); 	
}, add: function (other) {
	this.x += other.x; this.y += other.y; return this; 	
}, sub: function (other) {
	this.x -= other.x; this.y -= other.y; return this; 	
}, multiply: function (other) {
	this.x *= other.x; this.y *= other.y; return this; 	
}, negate: function() {
	this.x *= 1; this.y *= 1; return this; 	
}, length: function () {
	return Math.sqrt(this.x * this.x + this.y * this.y); 	
}, normalize: function (length) {
	length = length || 1; var div = ( 1 / this.length() ) * length; this.x *= div; this.y *= div; return this; 	
}, dot : function( other ) {
	return this.x * other.x + this.y * other.y; 	
}	
};


function distance(a,b) {
	var dx = a.x - b.x; var dy = a.y - b.y; var dz = a.z - b.z; return Math.sqrt( dx*dx + dy*dy + dz*dz ); 	
}

function getClosestFromList( point, list )
{
    var min  = 10e10;
    var dist = 0;
    var closest = null;
    list.forEach( function( p )
    {
        dist = distance( p, point );
        if( dist < min )
        {
            min = dist;
            closest = p;
        }
    });
    return closest;
}
/*
 * A speed-improved perlin and simplex noise algorithms for 2D.
 *
 * Based on example code by Stefan Gustavson (stegu@itn.liu.se).
 * Optimisations by Peter Eastman (peastman@drizzle.stanford.edu).
 * Better rank ordering method by Stefan Gustavson in 2012.
 * Converted to Javascript by Joseph Gentle.
 *
 * Version 2012-03-09
 *
 * This code was placed in the public domain by its original author,
 * Stefan Gustavson. You may use it as you see fit, but
 * attribution is appreciated.
 *
 */


var simplex = function( module )
{

    function Grad(x, y, z) {
        this.x = x; this.y = y; this.z = z;
    }

    Grad.prototype.dot2 = function(x, y) {
        return this.x*x + this.y*y;
    };

    Grad.prototype.dot3 = function(x, y, z) {
        return this.x*x + this.y*y + this.z*z;
    };

    var grad3 = [new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0),
        new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1),
        new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)];

    var p = [151,160,137,91,90,15, 131, 13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88, 237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77, 146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102, 143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135, 130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5, 202, 38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223, 183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129, 22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251, 34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49, 192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138, 236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180];

    // To remove the need for index wrapping, double the permutation table length
    var perm = new Array(512);
    var gradP = new Array(512);

    // This isn't a very good seeding function, but it works ok. It supports 2^16
    // different seed values. Write something better if you need more seeds.
    module.seed = function(seed) {
        if(seed > 0 && seed < 1) {
            // Scale the seed out
            seed *= 65536;
        }

        seed = Math.floor(seed);
        if(seed < 256) {
            seed |= seed << 8;
        }

        for(var i = 0; i < 256; i++) {
            var v;
            if (i & 1) {
                v = p[i] ^ (seed & 255);
            } else {
                v = p[i] ^ ((seed>>8) & 255);
            }

            perm[i] = perm[i + 256] = v;
            gradP[i] = gradP[i + 256] = grad3[v % 12];
        }
    };

    module.seed(0);

    /*
     for(var i=0; i<256; i++) {
     perm[i] = perm[i + 256] = p[i];
     gradP[i] = gradP[i + 256] = grad3[perm[i] % 12];
     }*/

    // Skewing and unskewing factors for 2, 3, and 4 dimensions
    var F2 = 0.5*(Math.sqrt(3)-1);
    var G2 = (3-Math.sqrt(3))/6;

    var F3 = 1/3;
    var G3 = 1/6;

    // 2D simplex noise
    module.simplex2 = function(xin, yin) {
        var n0, n1, n2; // Noise contributions from the three corners
        // Skew the input space to determine which simplex cell we're in
        var s = (xin+yin)*F2; // Hairy factor for 2D
        var i = Math.floor(xin+s);
        var j = Math.floor(yin+s);
        var t = (i+j)*G2;
        var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed.
        var y0 = yin-j+t;
        // For the 2D case, the simplex shape is an equilateral triangle.
        // Determine which simplex we are in.
        var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
        if(x0>y0) { // lower triangle, XY order: (0,0)->(1,0)->(1,1)
            i1=1; j1=0;
        } else {    // upper triangle, YX order: (0,0)->(0,1)->(1,1)
            i1=0; j1=1;
        }
        // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
        // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
        // c = (3-sqrt(3))/6
        var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
        var y1 = y0 - j1 + G2;
        var x2 = x0 - 1 + 2 * G2; // Offsets for last corner in (x,y) unskewed coords
        var y2 = y0 - 1 + 2 * G2;
        // Work out the hashed gradient indices of the three simplex corners
        i &= 255;
        j &= 255;
        var gi0 = gradP[i+perm[j]];
        var gi1 = gradP[i+i1+perm[j+j1]];
        var gi2 = gradP[i+1+perm[j+1]];
        // Calculate the contribution from the three corners
        var t0 = 0.5 - x0*x0-y0*y0;
        if(t0<0) {
            n0 = 0;
        } else {
            t0 *= t0;
            n0 = t0 * t0 * gi0.dot2(x0, y0);  // (x,y) of grad3 used for 2D gradient
        }
        var t1 = 0.5 - x1*x1-y1*y1;
        if(t1<0) {
            n1 = 0;
        } else {
            t1 *= t1;
            n1 = t1 * t1 * gi1.dot2(x1, y1);
        }
        var t2 = 0.5 - x2*x2-y2*y2;
        if(t2<0) {
            n2 = 0;
        } else {
            t2 *= t2;
            n2 = t2 * t2 * gi2.dot2(x2, y2);
        }
        // Add contributions from each corner to get the final noise value.
        // The result is scaled to return values in the interval [-1,1].
        return 70 * (n0 + n1 + n2);
    };

    // 3D simplex noise
    module.simplex3 = function(xin, yin, zin) {
        var n0, n1, n2, n3; // Noise contributions from the four corners

        // Skew the input space to determine which simplex cell we're in
        var s = (xin+yin+zin)*F3; // Hairy factor for 2D
        var i = Math.floor(xin+s);
        var j = Math.floor(yin+s);
        var k = Math.floor(zin+s);

        var t = (i+j+k)*G3;
        var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed.
        var y0 = yin-j+t;
        var z0 = zin-k+t;

        // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
        // Determine which simplex we are in.
        var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
        var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
        if(x0 >= y0) {
            if(y0 >= z0)      { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; }
            else if(x0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; }
            else              { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; }
        } else {
            if(y0 < z0)      { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; }
            else if(x0 < z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; }
            else             { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; }
        }
        // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
        // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
        // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
        // c = 1/6.
        var x1 = x0 - i1 + G3; // Offsets for second corner
        var y1 = y0 - j1 + G3;
        var z1 = z0 - k1 + G3;

        var x2 = x0 - i2 + 2 * G3; // Offsets for third corner
        var y2 = y0 - j2 + 2 * G3;
        var z2 = z0 - k2 + 2 * G3;

        var x3 = x0 - 1 + 3 * G3; // Offsets for fourth corner
        var y3 = y0 - 1 + 3 * G3;
        var z3 = z0 - 1 + 3 * G3;

        // Work out the hashed gradient indices of the four simplex corners
        i &= 255;
        j &= 255;
        k &= 255;
        var gi0 = gradP[i+   perm[j+   perm[k   ]]];
        var gi1 = gradP[i+i1+perm[j+j1+perm[k+k1]]];
        var gi2 = gradP[i+i2+perm[j+j2+perm[k+k2]]];
        var gi3 = gradP[i+ 1+perm[j+ 1+perm[k+ 1]]];

        // Calculate the contribution from the four corners
        var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0;
        if(t0<0) {
            n0 = 0;
        } else {
            t0 *= t0;
            n0 = t0 * t0 * gi0.dot3(x0, y0, z0);  // (x,y) of grad3 used for 2D gradient
        }
        var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1;
        if(t1<0) {
            n1 = 0;
        } else {
            t1 *= t1;
            n1 = t1 * t1 * gi1.dot3(x1, y1, z1);
        }
        var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2;
        if(t2<0) {
            n2 = 0;
        } else {
            t2 *= t2;
            n2 = t2 * t2 * gi2.dot3(x2, y2, z2);
        }
        var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3;
        if(t3<0) {
            n3 = 0;
        } else {
            t3 *= t3;
            n3 = t3 * t3 * gi3.dot3(x3, y3, z3);
        }
        // Add contributions from each corner to get the final noise value.
        // The result is scaled to return values in the interval [-1,1].
        return 32 * (n0 + n1 + n2 + n3);

    };

    // ##### Perlin noise stuff

    function fade(t) {
        return t*t*t*(t*(t*6-15)+10);
    }

    function lerp(a, b, t) {
        return (1-t)*a + t*b;
    }

    // 2D Perlin Noise
    module.perlin2 = function(x, y) {
        // Find unit grid cell containing point
        var X = Math.floor(x), Y = Math.floor(y);
        // Get relative xy coordinates of point within that cell
        x = x - X; y = y - Y;
        // Wrap the integer cells at 255 (smaller integer period can be introduced here)
        X = X & 255; Y = Y & 255;

        // Calculate noise contributions from each of the four corners
        var n00 = gradP[X+perm[Y]].dot2(x, y);
        var n01 = gradP[X+perm[Y+1]].dot2(x, y-1);
        var n10 = gradP[X+1+perm[Y]].dot2(x-1, y);
        var n11 = gradP[X+1+perm[Y+1]].dot2(x-1, y-1);

        // Compute the fade curve value for x
        var u = fade(x);

        // Interpolate the four results
        return lerp(
            lerp(n00, n10, u),
            lerp(n01, n11, u),
            fade(y));
    };

    // 3D Perlin Noise
    module.perlin3 = function(x, y, z) {
        // Find unit grid cell containing point
        var X = Math.floor(x), Y = Math.floor(y), Z = Math.floor(z);
        // Get relative xyz coordinates of point within that cell
        x = x - X; y = y - Y; z = z - Z;
        // Wrap the integer cells at 255 (smaller integer period can be introduced here)
        X = X & 255; Y = Y & 255; Z = Z & 255;

        // Calculate noise contributions from each of the eight corners
        var n000 = gradP[X+  perm[Y+  perm[Z  ]]].dot3(x,   y,     z);
        var n001 = gradP[X+  perm[Y+  perm[Z+1]]].dot3(x,   y,   z-1);
        var n010 = gradP[X+  perm[Y+1+perm[Z  ]]].dot3(x,   y-1,   z);
        var n011 = gradP[X+  perm[Y+1+perm[Z+1]]].dot3(x,   y-1, z-1);
        var n100 = gradP[X+1+perm[Y+  perm[Z  ]]].dot3(x-1,   y,   z);
        var n101 = gradP[X+1+perm[Y+  perm[Z+1]]].dot3(x-1,   y, z-1);
        var n110 = gradP[X+1+perm[Y+1+perm[Z  ]]].dot3(x-1, y-1,   z);
        var n111 = gradP[X+1+perm[Y+1+perm[Z+1]]].dot3(x-1, y-1, z-1);

        // Compute the fade curve value for x, y, z
        var u = fade(x);
        var v = fade(y);
        var w = fade(z);

        // Interpolate
        return lerp(
            lerp(
                lerp(n000, n100, u),
                lerp(n001, n101, u), w),
            lerp(
                lerp(n010, n110, u),
                lerp(n011, n111, u), w),
            v);
    };

    module.turbulence = function( x,y,z, size, octaves, lacunarity, gain )
    {
        lacunarity = lacunarity || 2;
        gain = gain || .5;

        var sum = 0;
        var  freq = size, amp = 1.0;
        for ( var i = 0; i < octaves; i++ )
        {
            var n = module.perlin3( freq * x, freq * y, freq * z );
            sum += n * amp;
            freq *= lacunarity;
            amp *= gain;
        }
        return sum;
    };

    return module;

}({});
/*
 from : http://en.wikipedia.org/wiki/Mersenne_twister
 */

var PRNG = function( exports ){

    var index = 0;
    
    // Create a length 624 array to store the state of the generator
    var MT = new Uint32Array( 624 );
    
    function initialize_generator( seed )
    {
        index = 0;
        MT[ 0 ] = seed;
        for( i = 1 ; i < 624; i++ )
        {
            MT[ i ] = ( 1812433253 * ( MT[i-1] ^ ( MT[ i-1 ] >> 30  ) + i ) );
        }
    }

    function extract_number()
    {
        if( index == 0 ) generate_numbers();

        var y = MT[ index ];
        y = y ^ ( y >> 11 );
        y = y ^ ( ( y << 7 ) & 2636928640 );
        y = y ^ ( ( y << 15 ) & 4022730752 );
        y = y ^ ( y >> 18 );

        index = ( index + 1 ) % 624;
        return y;
    }

    function generate_numbers()
    {
        for( var i = 0; i < 624; i++ )
        {
            var y = ( MT[ i ] & 0x80000000 ) + ( MT[( i + 1 ) % 624 ] & 0x7fffffff );
            MT[ i ] = MT[ ( i + 397 ) % 624] ^ ( y >> 1 );
            if ( y % 2 != 0 )
            {
                MT[ i ] = MT[ i ] ^ 2567483615;
            }
        }
    }

    exports.setSeed = function( seed )
    {
        initialize_generator(seed);
    };
    exports.random = function()
    {
        return ( extract_number() / 0x7FFFFFFF );
    };

    exports.setSeed(0);
    return exports;

}({});
/*
 //usage:

 PRNG.initialize_generator( seed );//seed: any int, uint or number

 PRNG.random(); //returns a pseudo-random value between 0 & 1
 */

/**
 * Created by nico on 13/09/2015.
 */
/**
 * checks if a value has a given bit set to 1
 * @value the int / uint to test
 * @mask the bits to check
 **/
function bit_isset( value, mask )
{
    return ( value & mask ) != 0;
}

/**
 * sets a bit mask to a int / uint
 * @value the int / uint to set the bit mask onto
 * @mask the bits to set
 **/
function bit_set( value, mask )
{
    value |= mask;
    return value;
}

/**
 * clears a bit mask
 * @value the int / uint to clear
 * @mask the bits to clear
 **/
function bit_clear( value, mask )
{
    value &= ~mask;
    return value;
}

/**
 * toggles a bit mask ( 1s become 0s & 0s become 1s )
 * @value the int / uint to toggle
 * @mask the bits to toggle
 **/
function bit_toggle( value, mask )
{
    value ^= mask;
    return value;
}

//////////////////////////////////////////////////////////////////

var interval;
var grids;
var noiseOffset;
var iter = 0;
var max = 100;
function init()
{
    iter = 0;
    ctx.clearRect(0,0,w,h);
    cancelAnimationFrame( interval );
    noiseOffset = Math.random() * 360;

    w = h = canvas.width = canvas.height = window.innerHeight / 2;
    canvas.width = w;
    canvas.height = h;

    var cellSize = powTwoCeil(w/2);

    grids = [
        //createGrid(w,h,cellSize/2 ),
        //createGrid(w,h,cellSize/4 ),
        createGrid(w,h,cellSize/8 ),
        createGrid(w,h,cellSize/16 ),
        createGrid(w,h,cellSize/32 ),
        createGrid(w,h,cellSize/64 )
    ];
    update();
}
function byTwo( x )
{
    return ~~( x ) + ~~( x ) % 2;
}

function powTwoFloor( x )
{
    var power = 1;
    while (x >>= 1) power <<= 1;
    return power;
}

function powTwoCeil( x )
{
    var power = 2;
    while (x >>= 1) power <<= 1;
    return power;
}

function update() {
    if( iter++ > max )
    {
        cancelAnimationFrame( interval );
        return;
    }

    ctx.restore();
    ctx.save();

    ctx.clearRect(0,0,w,h);
    interval = requestAnimationFrame(update);

    grids.forEach( function( grid, i ){

        var cellSize = grid.cellSize;
        var values = getValues(grid);
        var pix = [0,0,0 ];

        var prevGrid = i > 0 ? grids[ i - 1 ] : grid;
        var prevCoords;
        var sx = cellSize / w ;//* ( 1 /grids.length );
        var sy = cellSize / h ;//* ( 1 /grids.length );
        var a =  .15 + ( 1-i /grids.length ) * .85;
        ctx.globalAlpha = 1;// * 5;//a * 2;
        values.forEach(function(cell)
        {

            var n = simplex.simplex2( noiseOffset + cell.x * cellSize * sx, noiseOffset + cell.y * cellSize * sy );
            //if( Math.abs( n ) < 0 )return;

            prevCoords = getGridCoordinates( prevGrid, cell.x * cellSize, cell.y * cellSize );

            if( getGridValue( prevGrid, prevCoords.x, prevCoords.y ) )
            {

                ctx.shadowBlur = cellSize;
                ctx.shadowColor = ctx.fillStyle = "hsl( " + ( Math.abs( noiseOffset + n ) ) % 360  + ", 50%, "+ (  Math.abs( n ) * 100 + 25 ) +"% )";

                ctx.fillRect( cell.x * cellSize, cell.y * cellSize, cellSize, cellSize);

            }
        });

        var count = Math.max( 1, i ) * 2.5;

        for( var j =0; j < count; j++ )
        {
            var emptyCells = getEmptyCellsCoordinates(grid);

            if( emptyCells.length == 0 ){

                grid.full = true;
                return;
            }

            var randomId = ~~( emptyCells.length * Math.random() );

            // radially sorts a grid a picks the closest candidate to the center
            //if( i == grids.length -1 )
            //{
            //    emptyCells.sort( function(a,b)
            //    {
            //        var cx=grid.width/2, cy= grid.height/2;
            //        var dax,day,dbx,dby;
            //
            //        dax = cx - a[0];
            //        day = cy - a[1];
            //        dbx = cx - b[0];
            //        dby = cy - b[1];
            //
            //        var da = dax*dax + day*day;//distance( center, pa );//getNeighbours( grid, a[0], a[1], 0 ).length;
            //        var db = dbx*dbx + dby*dby;//distance( center, pb );//getNeighbours( grid, b[0], b[1], 0 ).length;
            //
            //        return ( da - db );
            //        //return ( db - da );
            //
            //    });
            //    randomId = 0;
            //}

            var p = new Point( emptyCells[ randomId ][0], emptyCells[ randomId ][1] );
            setGridValue( grid, p.x, p.y, p);
        }

    } );

}
window.onmousedown =
window.ontouchstart =
window.onresize =
window.onload = function()
{

    w = canvas.width = window.innerWidth;
    h = canvas.height = window.innerHeight;
    init();

};

/****************************************

 2D grid

 ****************************************/



function createGrid( width, height, size )
{
    var grid = [];
    for( var i = 0; i < width; i+= size )
    {
        var tmp = [];
        for( var j = 0; j < height; j+=size )
        {
            tmp.push( null );
        }
        grid.push( tmp );
    }
    grid.cellSize = size;
    grid.width  = Math.ceil( width / size );
    grid.height = Math.ceil( height / size );
    grid.cellCount = grid.width * grid.height;
    grid.full = false;
    return grid;
}

function getGridCoordinates(grid, x,y){

    return new Point( ~~( x / grid.cellSize ), ~~( y / grid.cellSize ) );
}

function setGridValue( grid, x,y, value ){

    var val = getGridValue( grid, x,y );
    if( val != null )return false;

    if( x < 0 || y < 0 || x > grid.width || y > grid.height )return false;
    grid[ x ][ y ] = value;
    return true;
}

function getGridValue( grid, x,y ){

    if( x < 0 || y < 0 || x > grid.width || y > grid.height )return null;
    return grid[ x ][ y ];
}

function getValues( grid ){

    var tmp = [];
    for( var i = 0; i < grid.width; i++ ){

        for( var j = 0; j < grid.height; j++ ){

            if( grid[ i ][ j ] != null ) tmp.push( grid[ i ][ j ] );
        }
    }
    return tmp;
}
function getEmptyCellsCoordinates( grid ){

    var tmp = [];
    for( var i = 0; i < grid.width; i++ ){

        for( var j = 0; j < grid.height; j++ ){

            if( grid[ i ][ j ] == null ) tmp.push( [ i,j ] );
        }
    }
    return tmp;
}

function getNeighbours( grid, x, y, offset )
{

    var minX = Math.max( 0, Math.min( grid.width,  x - offset ) );
    var maxX = Math.max( 0, Math.min( grid.width,  x + offset ) );
    var minY = Math.max( 0, Math.min( grid.height, y - offset ) );
    var maxY = Math.max( 0, Math.min( grid.height, y + offset ) );
    var tmp = [];
    for( var i = minX; i < maxX; i++ ){

        for( var j = minY; j < maxY; j++ ){

            if( grid[ i ][ j ] != null ) tmp.push( grid[ i ][ j ] );
        }
    }
    return tmp;
}
              
            
!
999px

Console