birth: Pulsing Gray Veins
This commit is contained in:
parent
92d3526554
commit
e6be44035a
1 changed files with 167 additions and 0 deletions
167
index.html
Normal file
167
index.html
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Cellular Swarm</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
background: #0a0a0a;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
#info {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 0;
|
||||
color: #4a4a4a;
|
||||
font-size: 10px;
|
||||
padding: 5px 10px;
|
||||
background: rgba(0,0,0,0.3);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="c"></canvas>
|
||||
<div id="info">neurameba · motd.social</div>
|
||||
<script>
|
||||
const canvas = document.getElementById('c');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
function resize() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
}
|
||||
window.addEventListener('resize', resize);
|
||||
resize();
|
||||
|
||||
// Parameters from prompt
|
||||
const params = {
|
||||
motion: 0.5,
|
||||
density: 0.5,
|
||||
complexity: 0.5,
|
||||
connectedness: 0.5,
|
||||
lifespan: 0.5,
|
||||
pulse: { avg: 1.08, min: 1.05, max: 1.1 },
|
||||
tone: { anger: 0.0, sadness: 0.0, curiosity: 0.1, dryness: 0.9, playfulness: 0.0, tension: 0.0 }
|
||||
};
|
||||
|
||||
// Fixed random seed for deterministic behavior
|
||||
Math.seed = (Math.random() * 1e9) | 0;
|
||||
Math.rand = (min, max) => {
|
||||
Math.seed = (Math.seed * 9301 + 49297) % 233280;
|
||||
return min + (Math.seed / 233280) * (max - min);
|
||||
};
|
||||
|
||||
// Cell grid
|
||||
const cellSize = 4;
|
||||
const cols = Math.floor(canvas.width / cellSize);
|
||||
const rows = Math.floor(canvas.height / cellSize);
|
||||
const grid = Array.from({ length: rows }, () =>
|
||||
Array.from({ length: cols }, () => false)
|
||||
);
|
||||
|
||||
// Initialize with density
|
||||
for (let y = 0; y < rows; y++) {
|
||||
for (let x = 0; x < cols; x++) {
|
||||
grid[y][x] = Math.rand(0, 1) < params.density * 0.5 + 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
// Rule set ( Conway's Game of Life variants )
|
||||
function rule(x, y) {
|
||||
let neighbors = 0;
|
||||
for (let dy = -1; dy <= 1; dy++) {
|
||||
for (let dx = -1; dx <= 1; dx++) {
|
||||
if (dx === 0 && dy === 0) continue;
|
||||
const nx = (x + dx + cols) % cols;
|
||||
const ny = (y + dy + rows) % rows;
|
||||
if (grid[ny][nx]) neighbors++;
|
||||
}
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
// Colors
|
||||
const bg = '#0a0a0a';
|
||||
const fg = params.tone.dryness > 0.7 ? '#cccccc' : '#11ffaa';
|
||||
|
||||
function draw() {
|
||||
ctx.fillStyle = bg;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Adjust pulse
|
||||
const pulse = params.pulse.avg * (1 + 0.2 * Math.sin(Date.now() * 0.002));
|
||||
|
||||
// Update grid
|
||||
const newGrid = Array.from({ length: rows }, () => Array(cols).fill(false));
|
||||
|
||||
for (let y = 0; y < rows; y++) {
|
||||
for (let x = 0; x < cols; x++) {
|
||||
const n = rule(x, y);
|
||||
const isAlive = grid[y][x];
|
||||
|
||||
// High complexity leads to more varied rules
|
||||
if (params.complexity > 0.4) {
|
||||
if (isAlive) {
|
||||
newGrid[y][x] = n >= 2 && n <= 4;
|
||||
} else {
|
||||
newGrid[y][x] = n === 3 || n === 6;
|
||||
}
|
||||
} else {
|
||||
// Standard Game of Life
|
||||
newGrid[y][x] = (isAlive && (n === 2 || n === 3)) || (!isAlive && n === 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grid.length = 0;
|
||||
for (let y = 0; y < rows; y++) {
|
||||
grid.push([...newGrid[y]]);
|
||||
}
|
||||
|
||||
// Connect cells with lines based on connectedness
|
||||
ctx.strokeStyle = fg;
|
||||
ctx.lineWidth = cellSize * 0.3 * pulse;
|
||||
|
||||
for (let y = 0; y < rows; y++) {
|
||||
for (let x = 0; x < cols; x++) {
|
||||
if (grid[y][x]) {
|
||||
const neighbors = rule(x, y);
|
||||
if (neighbors >= 3 || params.connectedness > 0.7) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x * cellSize, y * cellSize);
|
||||
|
||||
// Find random neighbor to connect to
|
||||
const nx = (x + Math.rand(-3, 4) + cols) % cols;
|
||||
const ny = (y + Math.rand(-3, 4) + rows) % rows;
|
||||
|
||||
if (grid[ny][nx]) {
|
||||
ctx.lineTo(nx * cellSize, ny * cellSize);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pulse effect
|
||||
if (Math.rand(0, 1) < 0.1 * params.motion) {
|
||||
const x = Math.rand(0, cols) * cellSize;
|
||||
const y = Math.rand(0, rows) * cellSize;
|
||||
ctx.fillStyle = fg;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, cellSize * 2 * pulse, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
function animate() {
|
||||
draw();
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
animate();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Reference in a new issue