Bits are Pixels
Just messing around.
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>
<canvas></canvas>
<div>
<p>
Bits are pixels with colour and direction. When they move, they colour the ground beneath.
When a bit meets another path it will change direction depending on the colour of the crossed path:
</p>
<ul>
<li>If the colour is the same as the bit, then it will continue in a random, orthogonal, direction</li>
<li>If the colour is different, then the bit will follow the path</li>
</ul>
</div>
<br>
<p>Below is documentation for the settings:</p>
<div>
<table class="tg">
<tr>
<th class="tg-9hbo">Setting</th>
<th class="tg-9hbo">Behaviour</th>
</tr>
<tr>
<td class="tg-yw4l">SPEED</td>
<td class="tg-yw4l">Number of steps each bit moves before the display updates</td>
</tr>
<tr>
<td class="tg-yw4l">NUM_BITS</td>
<td class="tg-yw4l">The number of bits </td>
</tr>
<tr>
<td class="tg-yw4l">FOLLOW</td>
<td class="tg-yw4l">If *checked*, then bits will follow the paths in the same direction they were made. Otherwise, bits follow in the opposite direction</td>
</tr>
<tr>
<td class="tg-baqh" colspan="2">Offset Settings - Normally a bit looks at the path beneath it. If an offset is used, then it will look at a path offset from itself</td>
</tr>
<tr>
<td class="tg-yw4l">OFFSET_X</td>
<td class="tg-yw4l">Offset in the horizontal direction. A value of 1 means look at the path 1 pixel to the right</td>
</tr>
<tr>
<td class="tg-yw4l">OFFSET_Y</td>
<td class="tg-yw4l">Offset in the vertical direction. A value of 1 means look at the path 1 pixel down</td>
</tr>
<tr>
<td class="tg-yw4l">RANDOM</td>
<td class="tg-yw4l">If *checked*, then OFFSET_X and OFFSET_Y are used as the absolute maximum offsets, and the offset per bit is randomly chosen upon generation</td>
</tr>
</table>
</div>
<br><br><br>
CSS
*{margin:24;font: 14px/22px Arial, sans-serif;}
body{background:#222;text-align:center;color:#f3eee8;margin-right:200px}
canvas{
background: rgba(0,0,0,0.5);
border:5px solid rgba(0,0,0,0.5);
display: inline-block;
padding: 0,200px,0,0;
}
div{text-align:left;}
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg .tg-baqh{text-align:center;vertical-align:top}
.tg .tg-9hbo{font-weight:bold;vertical-align:top}
.tg .tg-yw4l{vertical-align:top}
JavaScript
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var world = null;
var bits = null;
var settings = {
COLORS: ['#145C35', '#39A095', '#A2D4AE', '#EFDA94', '#EA7428'],
SPEED: 1,
NUM_BITS: 20,
FOLLOW: true,
OFFSET_X: 0,
OFFSET_Y: 0,
RAND_OFFSET: false,
INIT: function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
bits = [];
for(let i=0;i<settings.NUM_BITS;i++) {
let x = Math.floor(Math.random() * canvas.width);
let y = Math.floor(Math.random() * canvas.height);
let col = Math.floor(Math.random() * settings.COLORS.length);
let dir = Math.floor(Math.random() * 4);
let xo = settings.OFFSET_X;
let yo = settings.OFFSET_Y;
if (settings.RAND_OFFSET) {
xo = Math.floor(Math.random() * 2 * settings.OFFSET_X) - settings.OFFSET_X;
yo = Math.floor(Math.random() * 2 * settings.OFFSET_Y) - settings.OFFSET_Y;
}
bits.push(new Bit(x,y,col,dir,xo,yo));
}
world = [];
for (let x=0; x<canvas.width; x++) {
let row = [];
for (let y=0; y<canvas.height; y++) {
row.push({col: null, dir: null});
}
world.push(row);
}
}
}
var gui = new dat.GUI();
gui.add(settings, 'SPEED', 1, 100).step(1);
gui.add(settings, 'NUM_BITS', 1, 100).step(1).onFinishChange(settings.INIT);
gui.add(settings, 'FOLLOW');
var offsetFolder = gui.addFolder('Offset Settings');
offsetFolder.add(settings, 'OFFSET_X', -250, 250).step(1).onFinishChange(settings.INIT);
offsetFolder.add(settings, 'OFFSET_Y', -250, 250).step(1).onFinishChange(settings.INIT);
offsetFolder.add(settings, 'RAND_OFFSET').name('RANDOM').onFinishChange(settings.INIT);
gui.add(settings, 'INIT').name('RESET');
canvas.width = 600;
canvas.height = 600;
Number.prototype.mod = function(n) {
return ((this%n)+n)%n;
};
class Bit {
constructor(x,y,col,dir,xOffset,yOffset) {
this.x = x;
this.y = y;
this.col = col;
this.dir = dir;
this.xOffset = xOffset;
...