const gridLines = false;
const cellSize = 5;
const canvasWidth = 500;
const canvasHeight = 500;
const gridSize = canvasWidth / cellSize;
var generationHistory = [];
class Cell {
constructor(alive, posX, posY) {
this.alive = alive;
this.posX = posX;
this.posY = posY;
}
}
function setup() {
// initialise grid
var grid = [];
for(let i=0; i < gridSize; i++) {
grid[i] = new Array(gridSize);
}
//fill grid with cells.
for(let i = 0; i < gridSize; i++ ) {
for(let j = 0; j < gridSize; j++ ) {
grid[i][j] = new Cell(false, i*cellSize, j*cellSize);
}
}
if (!gridLines){
noStroke();
}
// Random initial state
for(let i = 0; i < gridSize; i++) {
for(let j = 0; j < gridSize; j++) {
let r = Math.random();
if (r < 0.1){
grid[i][j].alive = true;
}
}
}
generationHistory.push(grid);
createCanvas(canvasWidth, canvasHeight);
frameRate(1)
}
function updateCell(i, j, currentGenerationGrid, nextGenerationGrid) {
let count = 0;
let left = i - 1;
let right = i + 1;
let top = j - 1;
let bot = j + 1;
// make edges wrap
if (i === 0) left = gridSize - 1;
if (i === gridSize - 1) right = 0;
if (j === 0) top = gridSize - 1;
if (j === gridSize - 1) bot = 0;
if(currentGenerationGrid[left][top].alive)count++;
if(currentGenerationGrid[i][top].alive)count++;
if(currentGenerationGrid[right][top].alive)count++;
if(currentGenerationGrid[left][j].alive)count++;
if(currentGenerationGrid[right][j].alive)count++;
if(currentGenerationGrid[left][bot].alive)count++;
if(currentGenerationGrid[i][bot].alive)count++;
if(currentGenerationGrid[right][bot].alive)count++;
if((currentGenerationGrid[i][j].alive) && (count < 2 || count > 3)) {
nextGenerationGrid[i][j].alive = false;
} else if(count === 3 && !currentGenerationGrid[i][j].alive) {
nextGenerationGrid[i][j].alive = true;
} else if(currentGenerationGrid[i][j].alive && (count === 2 || count === 3)) {
nextGenerationGrid[i][j].alive = true;
}
}
function copyGrid(grid) {
let copy = [];
for(let i = 0; i < gridSize; i++) {
copy[i] = [];
for (let j=0; j< gridSize; j++){
copy[i][j] = new Cell(grid[i][j].alive, grid[i][j].posX, grid[i][j].posY);
}
}
return copy;
}
function draw() {
// clear the entire canvas
background(255);
var grid = generationHistory[generationHistory.length-1];
if (gridLines){
//draw grid
fill(200);
for(let i=0; i < gridSize; i++) {
for(let j=0; j < gridSize; j++) {
rect(grid[i][j].posX, grid[i][j].posY, cellSize, cellSize)
}
}
}
let currentGenerationGrid = copyGrid(grid);
let totalGrid = copyGrid(grid);
let nextGenerationGrid = copyGrid(grid);
generationHistory.push(nextGenerationGrid);
if (generationHistory.length > 44){
generationHistory.shift();
}
//draw history
var shade = 250;
for (let h = generationHistory.length-1; h >= 0; h--){
shade -= 5;
for(let i = 0; i < gridSize; i++) {
for(let j = 0; j < gridSize; j++) {
if (generationHistory[h][i][j].alive && !totalGrid[i][j].alive) {
totalGrid[i][j].alive = true;
fill(250-shade,250-shade,shade);
rect(grid[i][j].posX, grid[i][j].posY, cellSize, cellSize);
}
}
}
}
//draw live cells
fill(0);
for(let i = 0; i < gridSize; i++) {
for(let j = 0; j < gridSize; j++) {
if (grid[i][j].alive) {
rect(grid[i][j].posX, grid[i][j].posY, cellSize, cellSize);
}
}
}
for(let i = 0; i < gridSize; i++) {
for(let j = 0; j < gridSize; j++) {
updateCell(i, j, currentGenerationGrid, nextGenerationGrid);
}
}
}