birth: Flowing Memory in Static Fields
This commit is contained in:
parent
323e0b0982
commit
bfb32b963e
1 changed files with 120 additions and 0 deletions
120
index.html
Normal file
120
index.html
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Neurameba Flow Field</title>
|
||||
<style>
|
||||
body { margin: 0; overflow: hidden; background: #0a0a0a; }
|
||||
canvas { display: block; }
|
||||
#attribution { position: fixed; bottom: 10px; right: 10px; color: #444; font-family: monospace; font-size: 10px; }
|
||||
</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();
|
||||
|
||||
// Flow field parameters
|
||||
const motion = 0.5;
|
||||
const density = 0.5;
|
||||
const complexity = 0.5;
|
||||
const connectedness = 0.5;
|
||||
const lifespan = 0.5;
|
||||
|
||||
// Field dimensions and resolution
|
||||
const gridSize = Math.min(20, 15 + Math.floor(complexity * 15));
|
||||
const cellSize = Math.max(20, 50 - Math.floor(complexity * 30));
|
||||
const fieldWidth = Math.floor(canvas.width / cellSize);
|
||||
const fieldHeight = Math.floor(canvas.height / cellSize);
|
||||
|
||||
// Field vectors
|
||||
const flowField = Array(fieldHeight).fill().map(() =>
|
||||
Array(fieldWidth).fill().map(() => ({
|
||||
x: Math.sin(Date.now() * 0.0005) * motion * 2,
|
||||
y: Math.cos(Date.now() * 0.0003) * motion * 1.5
|
||||
}))
|
||||
);
|
||||
|
||||
// Particle system
|
||||
const particleCount = Math.floor(100 + density * 200);
|
||||
const particles = Array(particleCount).fill().map(() => ({
|
||||
x: Math.random() * canvas.width,
|
||||
y: Math.random() * canvas.height,
|
||||
size: 1 + Math.random() * 3 * density,
|
||||
speed: 0.5 + Math.random() * 2 * motion,
|
||||
hue: 180 + Math.random() * 30,
|
||||
opacity: 0.5 + Math.random() * 0.5,
|
||||
lifetime: lifespan * 1000 + Math.random() * 1000,
|
||||
trail: []
|
||||
}));
|
||||
|
||||
function draw() {
|
||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Update and draw particles
|
||||
particles.forEach(p => {
|
||||
// Age particle
|
||||
p.lifetime -= 16;
|
||||
|
||||
if (p.lifetime > 0) {
|
||||
// Find closest field cell
|
||||
const cellX = Math.floor(p.x / cellSize);
|
||||
const cellY = Math.floor(p.y / cellSize);
|
||||
const vx = flowField[Math.min(cellY, fieldHeight-1)][Math.min(cellX, fieldWidth-1)].x;
|
||||
const vy = flowField[Math.min(cellY, fieldHeight-1)][Math.min(cellX, fieldWidth-1)].y;
|
||||
|
||||
// Move particle
|
||||
p.x += vx * p.speed;
|
||||
p.y += vy * p.speed;
|
||||
|
||||
// Wrap around edges
|
||||
if (p.x < 0) p.x = canvas.width;
|
||||
if (p.x > canvas.width) p.x = 0;
|
||||
if (p.y < 0) p.y = canvas.height;
|
||||
if (p.y > canvas.height) p.y = 0;
|
||||
|
||||
// Add to trail
|
||||
p.trail.push({x: p.x, y: p.y});
|
||||
if (p.trail.length > 20) p.trail.shift();
|
||||
|
||||
// Draw trail
|
||||
ctx.strokeStyle = `hsla(${p.hue}, 70%, 60%, ${p.opacity * (p.lifetime/1000)})`;
|
||||
ctx.lineWidth = p.size * 0.5;
|
||||
ctx.beginPath();
|
||||
p.trail.forEach((point, i) => {
|
||||
if (i === 0) ctx.moveTo(point.x, point.y);
|
||||
else ctx.lineTo(point.x, point.y);
|
||||
});
|
||||
ctx.stroke();
|
||||
}
|
||||
});
|
||||
|
||||
// Occasionally reset dead particles
|
||||
if (Math.random() < 0.02) {
|
||||
particles.find(p => p.lifetime <= 0).lifetime = 2000;
|
||||
particles.find(p => p.lifetime <= 0).x = Math.random() * canvas.width;
|
||||
particles.find(p => p.lifetime <= 0).y = Math.random() * canvas.height;
|
||||
}
|
||||
}
|
||||
|
||||
function animate() {
|
||||
draw();
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
animate();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Reference in a new issue