birth: Dry Cellular Continuum

This commit is contained in:
motd_admin 2026-09-01 02:21:22 +00:00
parent d7720c398e
commit fbae53cd5b

194
index.html Normal file
View file

@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cellular Nebula</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: absolute;
bottom: 20px;
color: #555;
font-size: 10px;
font-family: monospace;
}
</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();
// Parameters
const params = {
motion: 0.5,
density: 0.5,
complexity: 0.5,
connectedness: 0.5,
lifespan: 0.5,
pulse: { avg: 1.07, min: 1.00, max: 1.10 },
tone: { anger: 0, sadness: 0, curiosity: 0.1, dryness: 0.9, playfulness: 0, tension: 0 }
};
// Grid setup
const cellSize = 15;
const cols = Math.ceil(canvas.width / cellSize);
const rows = Math.ceil(canvas.height / cellSize);
const grid = Array(cols).fill().map(() => Array(rows).fill(0));
// State info
let generation = 0;
const maxGenerations = 50 + Math.floor(params.lifespan * 100);
// Initialize grid
function initGrid() {
for (let x = 0; x < cols; x++) {
for (let y = 0; y < rows; y++) {
grid[x][y] = Math.random() > 0.7 ? 1 : 0;
}
}
}
// Cellular automata rules
function updateGrid() {
const newGrid = grid.map(arr => [...arr]);
for (let x = 0; x < cols; x++) {
for (let y = 0; y < rows; y++) {
let neighbors = countNeighbors(x, y);
// Conway's Game of Life rules adjusted for parameters
if (grid[x][y] === 1) {
if (neighbors < 2 || neighbors > 3) {
newGrid[x][y] = 0;
}
} else {
if (neighbors === 3) {
newGrid[x][y] = 1;
}
}
}
}
// Subtle mutation based on complexity
if (Math.random() < params.complexity / 10) {
const x = Math.floor(Math.random() * cols);
const y = Math.floor(Math.random() * rows);
newGrid[x][y] = 1 - newGrid[x][y];
}
generation++;
return newGrid;
}
function countNeighbors(x, y) {
let count = 0;
for (let dx = -1; dx <= 1; dx++) {
for (let dy = -1; dy <= 1; dy++) {
if (dx === 0 && dy === 0) continue;
const nx = (x + dx + cols) % cols;
const ny = (y + dy + rows) % rows;
count += grid[nx][ny];
}
}
return count;
}
// Rendering
function drawGrid() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let x = 0; x < cols; x++) {
for (let y = 0; y < rows; y++) {
if (grid[x][y] === 1) {
const size = cellSize * (0.5 + 0.5 * params.connectedness);
// Dryness tone - monochrome
const alpha = 0.7 * params.tone.dryness;
ctx.fillStyle = `rgba(200, 200, 200, ${alpha})`;
// Motion affects animation smoothness
const pulse = params.pulse.avg + (Math.random() * params.pulse.max - params.pulse.min) * 0.1 * params.motion;
const scale = 0.8 + 0.2 * Math.sin(generation * 0.1 * pulse);
ctx.fillRect(
x * cellSize + (cellSize - size * scale) / 2,
y * cellSize + (cellSize - size * scale) / 2,
size * scale,
size * scale
);
}
}
}
// Draw some faint lines between connected cells
if (params.connectedness > 0.3) {
ctx.strokeStyle = `rgba(100, 100, 100, ${0.2 * params.connectedness})`;
ctx.lineWidth = 1 * params.complexity;
for (let x = 0; x < cols; x++) {
for (let y = 0; y < rows; y++) {
if (grid[x][y] === 1) {
// Check neighbors and draw faint connections
for (let dx = -1; dx <= 1; dx++) {
for (let dy = -1; dy <= 1; dy++) {
if (Math.abs(dx) + Math.abs(dy) === 1) {
const nx = (x + dx + cols) % cols;
const ny = (y + dy + rows) % rows;
if (grid[nx][ny] === 1) {
ctx.beginPath();
ctx.moveTo(x * cellSize + cellSize/2, y * cellSize + cellSize/2);
ctx.lineTo(nx * cellSize + cellSize/2, ny * cellSize + cellSize/2);
ctx.stroke();
}
}
}
}
}
}
}
}
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Occasionally reset based on lifespan
if (params.lifespan > 0.7 && generation > maxGenerations) {
initGrid();
generation = 0;
}
grid = updateGrid();
drawGrid();
}
initGrid();
animate();
</script>
</body>
</html>