createCanvas(windowWidth, windowHeight);
cols = floor(windowWidth / squareSize);
rows = floor(windowHeight / squareSize);
colorMode(HSB, 360, 100, 100, 1);
game = new GameBoard(cols, rows);
let col1 = color('#C5D1EB');
let col2 = color('#395B50');
for (let i = 0; i <= 100; i++) {
colorTable.push(lerpColor(col1, col2, ratio));
background(color('#1F2F16'));
for (let x = 0; x < game.width; x++) {
for (let y = 0; y < game.height; y++) {
if (game.board[x][y].alive) {
fill(game.board[x][y].getColor());
stroke(game.board[x][y].getColor());
rect(x * squareSize, y * squareSize, squareSize, squareSize);
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
cols = floor(windowWidth / squareSize);
rows = floor(windowHeight / squareSize);
game = new GameBoard(cols, rows);
constructor(width, height) {
this.timeIncrement = 0.01;
this.board = Array.from({ length: width }, () => Array(height).fill(null));
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
this.board[x][y] = new Cell(x, y, random() > 0.5);
let neighbors = Array.from({ length: 3 }, () => Array(3).fill(null));
for (let i = -1; i <= 1; i++) {
for (let j = -1; j <= 1; j++) {
if (nx >= 0 && ny >= 0 && nx < this.width && ny < this.height && (i !== 0 || j !== 0)) {
neighbors[i + 1][j + 1] = this.board[nx][ny];
let newStates = Array.from({ length: this.width }, () => Array(this.height).fill(false));
for (let x = 0; x < this.width; x++) {
for (let y = 0; y < this.height; y++) {
newStates[x][y] = this.board[x][y].willLiveNextGen(this.getNeighbors(x, y));
this.board[x][y].advanceZ(this.timeIncrement);
this.board[x][y].updatePerlinValue();
for (let x = 0; x < this.width; x++) {
for (let y = 0; y < this.height; y++) {
this.board[x][y].alive = newStates[x][y];
constructor(x, y, alive) {
this.perlinThreshold = 0.6;
this.updatePerlinValue();
this.perlinValue = noise(54604 + this.x * 0.01, this.y * 0.01, this.z);
let index = round(this.age * 100);
return colorTable[index];
willLiveNextGen(neighbors) {
for (let row of neighbors) {
if (cell && cell.alive) {
if ((aliveNeighbors === 2 || aliveNeighbors === 3) && this.alive || this.perlinValue > this.perlinThreshold) {
this.age = Math.min(this.age + 0.1, 1);
if (aliveNeighbors === 3 && !this.alive || this.perlinValue > this.perlinThreshold) {
if (!this.alive && this.perlinValue > this.perlinThreshold) {