creative-coding/6/sketch.js
2025-06-08 23:53:26 +02:00

157 lines
3.9 KiB
JavaScript

// GAME OF LIFE PLUS LANGTON'S ANT
const sketch = function (p) {
const gridSize = [200, 200];
const cellSize = 4;
const ant_val = 20;
const game_val = 1;
const mouse_val = 20;
const fill_randomly = false;
const random_fill_value = 1;
let agent = { x: cellSize * 30, y: cellSize * 30, angle: 0 };
let cols, rows;
let grid = [];
let nextGrid = [];
let cActive, cInactive, cAnt;
p.setup = function () {
p.createCanvas(gridSize[0] * cellSize, gridSize[1] * cellSize).parent(
"sketch"
);
cols = p.width / cellSize;
rows = p.height / cellSize;
// Initialize grid
if (fill_randomly) {
grid = Array.from({ length: cols }, () =>
// Array.from => arg1: length of array, arg2: function for each item
Array.from({ length: rows }, () => ({
val: p.random() < 0.5 ? random_fill_value : 0,
}))
);
} else {
grid = Array.from({ length: cols }, () =>
Array.from({ length: rows }, () => ({ val: 0 }))
);
}
nextGrid = Array.from({ length: cols }, () => Array(rows).fill(0));
cActive = p.color(127, 0, 127, 255);
cInactive = p.color(0, 0, 0, 255);
cAnt = p.color(0, 255, 255, 255);
p.background(0);
p.frameRate(10);
};
p.draw = function () {
p.noStroke();
// Draw the grid
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
if (grid[i][j].val > 0) {
const brightness = p.map(grid[i][j].val, 0, ant_val, 50, 255); // Map range t0 50-255
p.fill(127, 0, brightness, 255);
} else {
p.fill(cInactive);
}
p.rect(i * cellSize, j * cellSize, cellSize, cellSize);
}
}
p.fill(cAnt);
p.rect(agent.x, agent.y, cellSize, cellSize);
// Langton's Ant logic
const col = Math.floor(agent.x / cellSize);
const row = Math.floor(agent.y / cellSize);
if (grid[col][row].val > 0) {
agent.angle += 90;
grid[col][row].val = 0;
} else {
agent.angle -= 90;
grid[col][row].val = ant_val;
}
agent.angle = (agent.angle + 360) % 360;
switch (agent.angle) {
case 0:
agent.y -= cellSize;
break;
case 90:
agent.x += cellSize;
break;
case 180:
agent.y += cellSize;
break;
case 270:
agent.x -= cellSize;
break;
}
agent.x = (agent.x + p.width) % p.width;
agent.y = (agent.y + p.height) % p.height;
// Game of Life logic
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
const neighbors = countNeighbors(i, j);
if (grid[i][j].val > 0) {
switch (neighbors) {
case 2:
case 3:
nextGrid[i][j] = grid[i][j].val;
break;
default:
nextGrid[i][j] = grid[i][j].val - 1;
break;
}
} else {
if (neighbors === 3) {
nextGrid[i][j] = game_val;
} else {
nextGrid[i][j] = 0;
}
}
}
}
// Swap grids
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
grid[i][j].val = nextGrid[i][j];
}
}
};
function countNeighbors(x, y) {
let count = 0;
for (let i = -1; i <= 1; i++) {
for (let j = -1; j <= 1; j++) {
if (i === 0 && j === 0) continue;
const col = (x + i + cols) % cols;
const row = (y + j + rows) % rows;
count += grid[col][row].val > 0 ? 1 : 0;
}
}
return count;
}
p.mouseClicked = function () {
const x = Math.floor(p.mouseX / cellSize);
const y = Math.floor(p.mouseY / cellSize);
if (x >= 0 && x < cols && y >= 0 && y < rows) {
grid[x][y].val = grid[x][y].val > 0 ? 0 : mouse_val;
}
};
p.keyPressed = function () {
if (p.keyCode === 32) {
p.isLooping() ? p.noLoop() : p.loop();
}
};
};
new p5(sketch);