Browse Source

basic implementation and rendering

Brandon Wong 7 years ago
commit
89b028520c
2 changed files with 140 additions and 0 deletions
  1. 127 0
      automata.js
  2. 13 0
      index.html

+ 127 - 0
automata.js

@@ -0,0 +1,127 @@
+
+
+const canvas = document.getElementById('canvas');
+
+canvas.width = window.innerWidth - 50;
+canvas.height = window.innerHeight - 50;
+
+const canvwidth = canvas.width,
+    canvheight = canvas.height,
+    ctx = canvas.getContext('2d');
+
+function randIndivC(a = 0, b = 255) {
+    return Math.floor(Math.random() * (b-a) + a);
+}
+function cts(c) {
+    const r = c.r < 16 ? '0' + c.r.toString(16) : c.r.toString(16),
+        g = c.g < 16 ? '0' + c.g.toString(16) : c.g.toString(16),
+        b = c.b < 16 ? '0' + c.b.toString(16) : c.b.toString(16);
+    return '#' + r + g + b;
+}
+function mixedColor(base) {
+    let randr = Math.floor(Math.random() * 200 + 55),
+        randg = Math.floor(Math.random() * 200 + 55),
+        randb = Math.floor(Math.random() * 200 + 55);
+    if( base ) {
+        randr = Math.floor((base.r + randr) / 2);
+        randg = Math.floor((base.g + randg) / 2);
+        randb = Math.floor((base.b + randb) / 2);
+    }
+    return cts({r:randr, g:randg, b:randb});
+}
+function primaryOrSecondary() {
+    const t = Math.random(),
+        w = Math.floor(Math.random() * 3);
+    if( t < 0.45 ) {
+        const r = w === 0 ? 255 : 0,
+            g = w === 1 ? 255 : 0,
+            b = w === 2 ? 255 : 0;
+        return {r, g, b};
+    }
+    else if( t < 0.9 ) {
+        const r = w !== 0 ? 255 : 0,
+            g = w !== 1 ? 255 : 0,
+            b = w !== 2 ? 255 : 0;
+        return {r, g, b};
+    }
+    else {
+        const r = randIndivC(100, 255),
+            g = randIndivC(100, 255),
+            b = randIndivC(100, 255);
+        return {r, g, b};
+    }
+}
+function spot(x, y, colour) {
+    ctx.save();
+    ctx.fillStyle = colour;
+    ctx.fillRect(x, y, 10, 10);
+    ctx.restore();
+}
+
+
+function generateInitialRow(lx = canvwidth / 10 + 1) {
+    const row = [];
+    for( let i = 0; i < lx; i++ ) {
+        row.push( Math.random() < 0.5 ? false : true );
+    }
+    return row;
+}
+const rules = {
+        "111": false,
+        "110": true,
+        "101": true,
+        "100": false,
+        "011": true,
+        "010": true,
+        "001": true,
+        "000": false,
+    };
+function applyRules(first, second, third) {
+    return rules[ [+first, +second, +third].join('') ];
+}
+function addRow(field) {
+    if( !field.length ) {
+        return field;
+    }
+    if( field[0].length < 3 ) {
+        return field;
+    }
+    const last = field[ field.length - 1 ],
+        newRow = last.map(function iter(val, ind) {
+            const first = last[ind - 1] || 0,
+                second = val,
+                third = last[ind + 1] || 0;
+            return applyRules(first, second, third);
+        });
+    field.push(newRow);
+    return field;
+}
+function drawRow(row, y) {
+    row.forEach(function spotter(val, ind) {
+        if( val ) {
+            const c = mixedColor(primaryOrSecondary());
+            spot(ind * 10, y, c);
+        }
+    });
+}
+
+
+
+function step(field) {
+    requestAnimationFrame(descend.bind(null, field));
+}
+function descend(field) {
+    const n = field.length - 1;
+    drawRow(field[n], n * 10);
+    field = addRow(field);
+    if( n * 10 < canvheight ) {
+        setTimeout(step, 100, field);
+    }
+    else {//TODO: remove this clause after tests
+        console.log('STOP!');
+    }
+}
+
+step([ generateInitialRow() ]);
+
+

+ 13 - 0
index.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Cellular Automata</title>
+</head>
+<body>
+    <canvas id="canvas"></canvas>
+    <!--<canvas id="canvas" width="500" height="400" style="border:1px solid black;"></canvas>-->
+    <script src="automata.js"></script>
+</body>
+</html>
+