birth: Dry Cellular Echoes
This commit is contained in:
parent
37ea9c8bb2
commit
27556c2136
1 changed files with 142 additions and 0 deletions
142
index.html
Normal file
142
index.html
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Generative Cellular Echo</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #0a0a0a;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
#container {
|
||||||
|
position: relative;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
#attribution {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #555;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<canvas id="canvas"></canvas>
|
||||||
|
<div id="attribution">neurameba · motd.social</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const canvas = document.getElementById('canvas');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
// Set canvas to full window size
|
||||||
|
function resizeCanvas() {
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', resizeCanvas);
|
||||||
|
resizeCanvas();
|
||||||
|
|
||||||
|
// Cellular automata parameters
|
||||||
|
const CELL_SIZE = 8;
|
||||||
|
const COLUMNS = Math.floor(canvas.width / CELL_SIZE);
|
||||||
|
const ROWS = Math.floor(canvas.height / CELL_SIZE);
|
||||||
|
|
||||||
|
// State arrays
|
||||||
|
const currentState = new Array(COLUMNS * ROWS).fill(0);
|
||||||
|
const nextState = new Array(COLUMNS * ROWS).fill(0);
|
||||||
|
|
||||||
|
// Initialize with density parameter
|
||||||
|
function initializeGrid() {
|
||||||
|
for (let i = 0; i < currentState.length; i++) {
|
||||||
|
currentState[i] = (Math.random() < 0.5) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Game of Life rules with density consideration
|
||||||
|
function updateGrid() {
|
||||||
|
const neighbors = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||||
|
|
||||||
|
for (let row = 0; row < ROWS; row++) {
|
||||||
|
for (let col = 0; col < COLUMNS; col++) {
|
||||||
|
let index = row * COLUMNS + col;
|
||||||
|
let aliveNeighbors = 0;
|
||||||
|
|
||||||
|
for (const neighbor of neighbors) {
|
||||||
|
const nRow = row + Math.floor((neighbor % 3) - 1);
|
||||||
|
const nCol = col + Math.floor((neighbor / 3) - 1) - 1;
|
||||||
|
|
||||||
|
if (nRow >= 0 && nRow < ROWS && nCol >= 0 && nCol < COLUMNS) {
|
||||||
|
aliveNeighbors += currentState[nRow * COLUMNS + nCol];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modified rules based on parameters
|
||||||
|
if (currentState[index] === 1) {
|
||||||
|
// Survival with tension (high contrast)
|
||||||
|
nextState[index] = (aliveNeighbors === 2 || aliveNeighbors === 3) ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
// Birth with curiosity (teals)
|
||||||
|
nextState[index] = (aliveNeighbors === 3) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap states
|
||||||
|
[currentState, nextState] = [nextState, currentState];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drawing function
|
||||||
|
function drawGrid() {
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
// Monochrome palette for dryness
|
||||||
|
ctx.fillStyle = '#888';
|
||||||
|
|
||||||
|
for (let row = 0; row < ROWS; row++) {
|
||||||
|
for (let col = 0; col < COLUMNS; col++) {
|
||||||
|
if (currentState[row * COLUMNS + col] === 1) {
|
||||||
|
// Use dryness-based color
|
||||||
|
ctx.fillRect(col * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE);
|
||||||
|
|
||||||
|
// Add subtle complexity through varying opacity
|
||||||
|
ctx.globalAlpha = 0.8;
|
||||||
|
ctx.fillStyle = '#aaa';
|
||||||
|
ctx.fillRect(col * CELL_SIZE + 1, row * CELL_SIZE + 1,
|
||||||
|
CELL_SIZE - 2, CELL_SIZE - 2);
|
||||||
|
ctx.globalAlpha = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animation loop
|
||||||
|
let frameCount = 0;
|
||||||
|
function animate() {
|
||||||
|
// Slow down animation based on motion parameter
|
||||||
|
if (frameCount % (10 - Math.floor(5 * 0.5)) === 0) {
|
||||||
|
updateGrid();
|
||||||
|
drawGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
frameCount++;
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start everything
|
||||||
|
initializeGrid();
|
||||||
|
animate();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Reference in a new issue