<canvas id="gol" width="1000" height="1000"></canvas>
<div class="content">
<form onchange="changeMode(this.mode.value)">
<h3>Mode:</h3>
<label for="classic">
<input type="radio" name="mode" id="classic" value="classic">
Classic
</label>
<label for="smooth">
<input type="radio" name="mode" id="smooth" value="smooth">
Smooth
</label>
<label for="shiny">
<input type="radio" name="mode" id="shiny" value="shiny">
Shinny
</label>
<label for="blob">
<input type="radio" name="mode" id="blob" value="blob" checked>
Blob
</label>
</form>
<h1>
<small id="conway">Conway's</small><br/>
Game <small>Of</small> Life
</h1>
body {
margin: 0;
background-color: #000;
color: #fff;
font-family: sans-serif;
}
small {
font-size: 0.65em;
}
#gol {
display: block;
margin: 0 0 0 auto;
max-width: 100%;
max-height: 100vh;
width: auto;
height: auto;
border-radius: 50%;
}
.content {
position: fixed;
bottom: 4vw;
left: 4vw;
}
h1 {
margin: 0;
z-index: 1;
font-size: 10vh;
transform-origin: left;
text-shadow: 2px 2px 10px rgba(0,0,0,0.3);
}
label {
padding: 0.25em 0.5em 0.25em 0.25em;
margin-right: 0.5em;
font-size: .75em;
border-radius: 2em;
border: 1px solid #777;
background-color: rgba(0,0,0,0.5);
cursor: pointer;
}
label:hover {
border-color: #fff;
}
FRAME_RATE = 30; // fps interger
HAZARD = 100; // integer for ms, 0 for inactive
var canvas = document.getElementById("gol");
var ctx = canvas.getContext("2d");
function newMap() {
map = []
for (var i = 0; i < 100; i++) {
var suBmap = [];
for (var j = 0; j < 100; j++) {
suBmap.push(Math.random() > 0.5);
}
map.push(suBmap)
}
// console.log('map generated')
return map;
}
dataArray = newMap();
// // Change GoL String into an Array of Arrays
// var dataArray = data.split('\n').reduce((acc, cur) => {
// return acc = [
// ...acc,
// Array.from(cur).map(cell => parseInt(cell))
// ]
// }, [])
function random_rgba() {
var o = Math.round, r = Math.random, s = 255;
return 'rgba(' + o(r()*s) + ',' + o(r()*s) + ',' + o(r()*s) + ',' + r().toFixed(1) + ')';
}
function draw() {
dataArray.forEach((line, y) => {
line.forEach((cell, x) => {
ctx.fillStyle = cell ? "#fff" : "#000";
if (MODE === 'shiny') {
ctx.fillStyle = cell ? random_rgba() : "rgba(0,0,0,0.05)";
}
if (MODE === 'smooth' || MODE === 'blob') {
ctx.fillStyle = cell ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.05)";
}
ctx.fillRect((x-1)*10, (y-1)*10, 10, 10);
})
})
// console.log('map drawn')
}
function newCycle() {
dataArray = dataArray.reduce((res, line, y) => {
return res = [
...res,
line.map((cell, x) => {
if (x > 0 && y > 0 && x < 99 && y < 99) { // prevent to process the edge
let suroundings = [
dataArray[y-1][x], // top
dataArray[y-1][x-1], // top-left
dataArray[y-1][x+1], // top-right
dataArray[y][x-1], // left
dataArray[y][x+1], // right
dataArray[y+1][x], // bottom
dataArray[y+1][x-1], // bottom-left
dataArray[y+1][x+1] // bottom-right
]
suroundings = suroundings.reduce((acc, cur) => acc += cur , 0);
if (cell) {
return cell = suroundings === 2 || suroundings === 3 ? 1 : 0;
} else {
return cell = suroundings === 3 ? 1 : 0;
}
}
})
]
}, [])
// console.log('new cycle')
}
function toggleCell(x, y, big){
dataArray[x][y] = !dataArray[x][y];
if (dataArray && big) {
dataArray[x+1][y] = !dataArray[x+1][y];//right
dataArray[x-3][y] = !dataArray[x-3][y];//left
dataArray[x-1][y] = !dataArray[x-1][y];//top
dataArray[x][y+1] = !dataArray[x-1][y+1];//bottom
dataArray[x+3][y] = !dataArray[x+3][y];//right
dataArray[x-5][y] = !dataArray[x-5][y];//left
dataArray[x-3][y] = !dataArray[x-3][y];//top
dataArray[x][y+3] = !dataArray[x-3][y+3];//bottom
// wtf
dataArray[x+3][y] = !dataArray[x+3][y];//right
dataArray[x-5][y] = !dataArray[x-5][y];//left
dataArray[x-3][y] = !dataArray[x-3][y];//top
dataArray[x-3][y+3] = !dataArray[x-3][y+3];//bottom
dataArray[x+5][y] = !dataArray[x+5][y];//right
dataArray[x-7][y] = !dataArray[x-7][y];//left
dataArray[x-5][y] = !dataArray[x-5][y];//top
dataArray[x-5][y+5] = !dataArray[x-5][y+5];//bottom
}
}
function changeMode(mode) {
MODE = mode ? mode : 'blob';
switch (MODE) {
case 'classic':
return canvas.style = "";
case 'smooth':
return canvas.style = "";
case 'shiny':
return canvas.style = "filter: blur(1px) contrast(10)";
case 'blob':
return canvas.style = "filter: blur(7px) contrast(50)";
default:
return false;
}
}
document.addEventListener('DOMContentLoaded', function() {
changeMode();
// hover to generate life forms
canvas.addEventListener('mousemove', function(e){
const x = parseInt((e.clientX - canvas.getBoundingClientRect().left) * 100 / canvas.offsetWidth)
const y = parseInt((e.clientY - canvas.getBoundingClientRect().top) * 100 / canvas.offsetHeight)
toggleCell(y, x, true)
})
// generated random life forms
if (HAZARD) {
const loopRand = window.setInterval(function(){
toggleCell(parseInt(Math.random()*100), parseInt(Math.random()*100), true)
}, HAZARD)
}
// main loop
const loop = window.setInterval(function(){
newCycle();
draw();
}, 1000/FRAME_RATE)
})
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.