monochrome-cellular-excavat.../index.html

162 lines
5.8 KiB
HTML
Raw Permalink Normal View History

2026-09-20 22:21:22 +00:00
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neurameba · motd.social</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #0a0a0a;
font-family: 'Courier New', monospace;
}
canvas {
display: block;
}
#attribution {
position: absolute;
bottom: 10px;
right: 10px;
color: #333;
font-size: 10px;
text-shadow: 0 0 5px rgba(255,255,255,0.1);
}
</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 tuned for dryness/monochrome
const params = {
diffusionRateA: 1.0,
diffusionRateB: 0.5,
feedRate: 0.055,
killRate: 0.062,
timeStep: 1.0,
gridWidth: 80,
gridHeight: 45,
cellSize: 8,
decay: 0.99,
palette: ['#111', '#222', '#333', '#444', '#555'],
motion: 0.5,
density: 0.5,
paletteIndex: 0
};
// Initialize grids
let grid = new Array(params.gridHeight);
let nextGrid = new Array(params.gridHeight);
for (let i = 0; i < params.gridHeight; i++) {
grid[i] = new Array(params.gridWidth).fill(0);
nextGrid[i] = new Array(params.gridWidth).fill(0);
}
// Initialize with sparse random patterns
function initGrid() {
for (let y = 0; y < params.gridHeight; y++) {
for (let x = 0; x < params.gridWidth; x++) {
grid[y][x] = Math.random() > 0.95 ? 1 : 0;
}
}
}
// React-diffuse step
function reactDiffuse() {
for (let y = 0; y < params.gridHeight; y++) {
for (let x = 0; x < params.gridWidth; x++) {
const a = grid[y][x];
const b = grid[y][(x + 1) % params.gridWidth] +
grid[y][(x - 1 + params.gridWidth) % params.gridWidth] +
grid[(y + 1) % params.gridHeight][x] +
grid[(y - 1 + params.gridHeight) % params.gridHeight][x];
const laplacianA = (grid[(y + 1) % params.gridHeight][x] +
grid[(y - 1 + params.gridHeight) % params.gridHeight][x] +
grid[y][(x + 1) % params.gridWidth] +
grid[y][(x - 1 + params.gridWidth) % params.gridWidth] -
4 * a) / 4;
const laplacianB = (nextGrid[(y + 1) % params.gridHeight][x] +
nextGrid[(y - 1 + params.gridHeight) % params.gridHeight][x] +
nextGrid[y][(x + 1) % params.gridWidth] +
nextGrid[y][(x - 1 + params.gridWidth) % params.gridWidth] -
4 * b) / 4;
const reaction = a * b * b;
const newA = a + (params.diffusionRateA * laplacianA - reaction + params.feedRate * (1 - a)) * params.timeStep;
const newB = b + (params.diffusionRateB * laplacianB + reaction - (params.killRate + params.feedRate) * b) * params.timeStep;
nextGrid[y][x] = Math.min(Math.max(newA, 0), 1);
}
}
// Swap grids
[grid, nextGrid] = [nextGrid, grid];
// Apply decay to prevent perfect patterns
for (let y = 0; y < params.gridHeight; y++) {
for (let x = 0; x < params.gridWidth; x++) {
grid[y][x] *= params.decay;
}
}
}
// Draw with variable palette based on parameters
function draw() {
const width = params.gridWidth * params.cellSize;
const height = params.gridHeight * params.cellSize;
for (let y = 0; y < params.gridHeight; y++) {
for (let x = 0; x < params.gridWidth; x++) {
const value = grid[y][x];
if (value > 0.01) {
const intensity = Math.min(value * 255, 255);
ctx.fillStyle = params.palette[params.paletteIndex];
ctx.globalAlpha = value;
ctx.fillRect(x * params.cellSize, y * params.cellSize,
params.cellSize, params.cellSize);
}
}
}
ctx.globalAlpha = 1;
}
// Animate and update parameters over time
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Adjust parameters based on time
const time = Date.now() * 0.0005;
params.feedRate = 0.055 + Math.sin(time * 0.5) * 0.01;
params.killRate = 0.062 + Math.cos(time * 0.3) * 0.01;
// Occasionally change palette
if (Math.random() < 0.002) {
params.paletteIndex = Math.floor(Math.random() * params.palette.length);
}
reactDiffuse();
draw();
requestAnimationFrame(animate);
}
initGrid();
animate();
</script>
</body>
</html>
```