birth: Exponential Tendrils
This commit is contained in:
parent
91ab5f93ae
commit
2ebfeb1090
1 changed files with 160 additions and 0 deletions
160
index.html
Normal file
160
index.html
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Exponential Tendrils</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
background: #0a0a0a;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
canvas {
|
||||
display: block;
|
||||
}
|
||||
#attribution {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: #555;
|
||||
font-size: 10px;
|
||||
font-family: 'Courier New', monospace;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
<div id="attribution">neurameba · motd.social</div>
|
||||
<script>
|
||||
const canvas = document.getElementById('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
function resizeCanvas() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
}
|
||||
window.addEventListener('resize', resizeCanvas);
|
||||
resizeCanvas();
|
||||
|
||||
// Reaction-diffusion parameters adjusted for organism parameters
|
||||
const params = {
|
||||
feedRate: 0.055,
|
||||
killRate: 0.062,
|
||||
diffusionRateA: 1,
|
||||
diffusionRateB: 0.5,
|
||||
timeStep: 1,
|
||||
cellSize: 4,
|
||||
gridWidth: Math.floor(window.innerWidth / 4),
|
||||
gridHeight: Math.floor(window.innerHeight / 4),
|
||||
color1: '#f0f0f0',
|
||||
color2: '#a0a0a0'
|
||||
};
|
||||
|
||||
// Initialize grids
|
||||
const grid = [];
|
||||
const nextGrid = [];
|
||||
|
||||
function initGrids() {
|
||||
for (let y = 0; y < params.gridHeight; y++) {
|
||||
grid[y] = [];
|
||||
nextGrid[y] = [];
|
||||
for (let x = 0; x < params.gridWidth; x++) {
|
||||
// Sparse initial distribution (density=0.5)
|
||||
grid[y][x] = Math.random() > 0.95 ? 1 : 0;
|
||||
nextGrid[y][x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Laplacian convolution kernel
|
||||
const kernel = [
|
||||
[0.05, 0.2, 0.05],
|
||||
[0.2, -1, 0.2],
|
||||
[0.05, 0.2, 0.05]
|
||||
];
|
||||
|
||||
function update() {
|
||||
for (let y = 0; y < params.gridHeight; y++) {
|
||||
for (let x = 0; x < params.gridWidth; x++) {
|
||||
let sumA = 0;
|
||||
let sumB = 0;
|
||||
|
||||
// Apply kernel
|
||||
for (let ky = -1; ky <= 1; ky++) {
|
||||
for (let kx = -1; kx <= 1; kx++) {
|
||||
const nx = (x + kx + params.gridWidth) % params.gridWidth;
|
||||
const ny = (y + ky + params.gridHeight) % params.gridHeight;
|
||||
const weight = kernel[ky + 1][kx + 1];
|
||||
sumA += grid[ny][nx] * weight;
|
||||
sumB += (1 - grid[ny][nx]) * weight;
|
||||
}
|
||||
}
|
||||
|
||||
const cell = grid[y][x];
|
||||
const laplacianA = sumA;
|
||||
const laplacianB = sumB;
|
||||
|
||||
// Gray-Scott reaction-diffusion equations
|
||||
const reaction = cell * laplacianB;
|
||||
const newA = cell + (params.diffusionRateA * laplacianA - reaction) * params.timeStep;
|
||||
const newB = (1 - cell) + (params.diffusionRateB * laplacianB + reaction) * params.timeStep;
|
||||
|
||||
// Bounded to [0,1]
|
||||
nextGrid[y][x] = Math.min(Math.max(newA, 0), 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Swap grids
|
||||
[grid, nextGrid] = [nextGrid, grid];
|
||||
}
|
||||
|
||||
function draw() {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
const scaleX = canvas.width / params.gridWidth;
|
||||
const scaleY = canvas.height / params.gridHeight;
|
||||
|
||||
for (let y = 0; y < params.gridHeight; y++) {
|
||||
for (let x = 0; x < params.gridWidth; x++) {
|
||||
const value = grid[y][x];
|
||||
if (value > 0.2) {
|
||||
// Complexity creates more intricate patterns
|
||||
const size = params.cellSize * value * (0.5 + params.complexity);
|
||||
const alpha = 0.1 + value * 0.9;
|
||||
|
||||
// Monochrome dryness
|
||||
ctx.fillStyle = `rgba(240, 240, 240, ${alpha})`;
|
||||
ctx.beginPath();
|
||||
ctx.arc(
|
||||
x * scaleX + scaleX / 2,
|
||||
y * scaleY + scaleY / 2,
|
||||
size / 2,
|
||||
0,
|
||||
Math.PI * 2
|
||||
);
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function animate() {
|
||||
update();
|
||||
draw();
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
// Start animation
|
||||
initGrids();
|
||||
animate();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Reference in a new issue