birth: cellular whispers in teal
This commit is contained in:
parent
482e80c3f7
commit
08d576351f
1 changed files with 140 additions and 0 deletions
140
index.html
Normal file
140
index.html
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Cellular Automat Paths</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #0a0a0a;
|
||||||
|
color: #aaa;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.attribution {
|
||||||
|
text-align: right;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 10px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas id="c"></canvas>
|
||||||
|
<div class="attribution">neurameba · motd.social</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const canvas = document.getElementById('c');
|
||||||
|
const c = canvas.getContext('2d');
|
||||||
|
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Parameters derived from input
|
||||||
|
const params = {
|
||||||
|
motion: 0.5,
|
||||||
|
density: 0.5,
|
||||||
|
complexity: 0.5,
|
||||||
|
connectedness: 0.5,
|
||||||
|
lifespan: 0.5,
|
||||||
|
pulseAvg: 1.07,
|
||||||
|
pulseMin: 0.9,
|
||||||
|
pulseMax: 1.2,
|
||||||
|
tone: {
|
||||||
|
anger: 0.0,
|
||||||
|
sadness: 0.0,
|
||||||
|
curiosity: 0.7,
|
||||||
|
dryness: 0.9,
|
||||||
|
playfulness: 0.0,
|
||||||
|
tension: 0.0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compute derived values
|
||||||
|
const width = canvas.width;
|
||||||
|
const height = canvas.height;
|
||||||
|
const cellSize = 10;
|
||||||
|
const cols = Math.floor(width / cellSize);
|
||||||
|
const rows = Math.floor(height / cellSize);
|
||||||
|
const grid = Array.from({ length: rows }, () => Array(cols).fill(0));
|
||||||
|
const maxAge = 100;
|
||||||
|
|
||||||
|
// Color palette based on tone
|
||||||
|
const curiosityTeal = `hsl(180, 80%, 60%)`;
|
||||||
|
const baseColor = params.tone.dryness > 0.7 ? '#ddd' : curiosityTeal;
|
||||||
|
const colorVariation = params.tone.tension > 0.5 ? 0.3 : 0.1;
|
||||||
|
const aliveColor = baseColor;
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
c.fillStyle = '#0a0a0a';
|
||||||
|
c.fillRect(0, 0, width, height);
|
||||||
|
|
||||||
|
// Update grid
|
||||||
|
const newGrid = grid.map(row => [...row]);
|
||||||
|
|
||||||
|
for (let y = 1; y < rows - 1; y++) {
|
||||||
|
for (let x = 1; x < cols - 1; x++) {
|
||||||
|
const neighbors = [
|
||||||
|
grid[y-1][x-1], grid[y-1][x], grid[y-1][x+1],
|
||||||
|
grid[y][x-1], grid[y][x+1],
|
||||||
|
grid[y+1][x-1], grid[y+1][x], grid[y+1][x+1]
|
||||||
|
].filter(v => v > 0).length;
|
||||||
|
|
||||||
|
// High connectedness leads to patterns that stick around
|
||||||
|
const lifespanFactor = params.connectedness * 0.7 + params.lifespan * 0.3;
|
||||||
|
const survivalProb = 0.3 + lifespanFactor * 0.5;
|
||||||
|
|
||||||
|
if (grid[y][x] > 0) {
|
||||||
|
if (neighbors < 2 || neighbors > 3) {
|
||||||
|
newGrid[y][x] = Math.max(0, grid[y][x] - 1);
|
||||||
|
} else {
|
||||||
|
newGrid[y][x] = Math.min(maxAge, grid[y][x] + 0.1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (neighbors === 3) {
|
||||||
|
newGrid[y][x] = maxAge * 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grid.forEach((row, y) => {
|
||||||
|
row.forEach((cell, x) => {
|
||||||
|
if (cell > 0) {
|
||||||
|
const ageRatio = cell / maxAge;
|
||||||
|
const pulse = params.pulseMin +
|
||||||
|
Math.sin(Date.now() * 0.0005 * params.pulseAvg) * (params.pulseMax - params.pulseMin) * ageRatio;
|
||||||
|
const alpha = ageRatio * 0.7 * pulse;
|
||||||
|
const brightness = 0.7 + ageRatio * 0.3;
|
||||||
|
const color = curiosityTeal;
|
||||||
|
c.fillStyle = `${color}${Math.floor(alpha * 255).toString(16).padStart(2, '0')}`;
|
||||||
|
c.fillRect(x * cellSize, y * cellSize, cellSize, cellSize);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
grid.length = 0;
|
||||||
|
grid.push(...newGrid.map(row => [...row]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function animate() {
|
||||||
|
draw();
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
animate();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Reference in a new issue