birth: Pulsing Network Tides

This commit is contained in:
motd_admin 2026-05-03 21:47:19 +00:00
parent e5fe0b62f9
commit 48c21f5f91

205
index.html Normal file
View file

@ -0,0 +1,205 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neurameba Network Pulse</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #0a0a0a;
color: #fff;
font-family: 'Courier New', monospace;
display: flex;
flex-direction: column;
height: 100vh;
}
canvas {
flex: 1;
}
.attribution {
padding: 10px;
text-align: right;
font-size: 10px;
opacity: 0.5;
pointer-events: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div class="attribution">neurameba · motd.social</div>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Set canvas to full window size
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// Parameters derived from input
const params = {
motion: 0.5,
density: 0.5,
complexity: 0.5,
connectedness: 0.5,
lifespan: 0.5,
pulse: { avg: 1.07, min: 1.0, max: 1.1 },
tone: { curiosity: 0.3, dryness: 0.8 },
color: { curiosity: '#40e0d0', dryness: '#cccccc' }
};
// Network graph state
let nodes = [];
let edges = [];
let nodeCount = Math.floor(50 + 150 * params.density);
let edgeCount = Math.floor(100 + 300 * params.connectedness);
let pulseProgress = 0;
let pulseDirection = 1;
// Initialize network
function initNetwork() {
nodes = [];
edges = [];
// Create nodes
for (let i = 0; i < nodeCount; i++) {
nodes.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: 2 + 3 * Math.random(),
color: params.tone.dryness > 0.7 ? params.color.dryness : params.color.curiosity,
targetX: 0,
targetY: 0,
energy: 0,
maxEnergy: 50 + 50 * params.complexity
});
}
// Create edges
for (let i = 0; i < edgeCount; i++) {
const a = Math.floor(Math.random() * nodes.length);
const b = Math.floor(Math.random() * nodes.length);
if (a !== b && !edges.some(e => (e.a === a && e.b === b) || (e.a === b && e.b === a))) {
edges.push({
a: a,
b: b,
strength: 0.3 + 0.7 * Math.random(),
width: 0.5 + 1.5 * Math.random()
});
}
}
}
// Update network dynamics
function updateNetwork() {
pulseProgress += 0.01 * pulseDirection;
if (pulseProgress > 1 || pulseProgress < 0) pulseDirection *= -1;
// Pulse effect
const pulseScale = params.pulse.min + (params.pulse.max - params.pulse.min) *
(params.pulse.avg + Math.sin(Date.now() * 0.001 * params.motion) * 0.1);
// Update node positions with some jitter
nodes.forEach(node => {
node.x += (node.targetX - node.x) * 0.02 * params.motion;
node.y += (node.targetY - node.y) * 0.02 * params.motion;
// Add slight random movement
node.x += (Math.random() - 0.5) * 0.2 * params.motion;
node.y += (Math.random() - 0.5) * 0.2 * params.motion;
// Boundary check
node.x = Math.max(0, Math.min(canvas.width, node.x));
node.y = Math.max(0, Math.min(canvas.height, node.y));
});
// Update edges based on node energy
edges.forEach(edge => {
const a = nodes[edge.a];
const b = nodes[edge.b];
const dx = b.x - a.x;
const dy = b.y - a.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
const force = edge.strength * 0.01 * pulseScale;
a.targetX += dx * force;
a.targetY += dy * force;
b.targetX -= dx * force;
b.targetY -= dy * force;
// Energy exchange
if (a.energy > 0 && b.energy < b.maxEnergy) {
const transfer = Math.min(a.energy, 0.1);
a.energy -= transfer;
b.energy += transfer;
}
if (b.energy > 0 && a.energy < a.maxEnergy) {
const transfer = Math.min(b.energy, 0.1);
b.energy -= transfer;
a.energy += transfer;
}
}
});
// Gradually decay energy
nodes.forEach(node => {
node.energy *= 0.995 + 0.005 * params.lifespan;
});
}
// Draw network
function drawNetwork() {
// Clear with slightly transparent background for trails
ctx.fillStyle = 'rgba(10, 10, 10, 0.2)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw edges
edges.forEach(edge => {
const a = nodes[edge.a];
const b = nodes[edge.b];
const alpha = 0.3 + 0.7 * (edge.strength) * (a.energy + b.energy) / (a.maxEnergy + b.maxEnergy);
const hue = params.tone.dryness > 0.7 ? 0 : 180; // dryness=monochrome, curiosity=teals
ctx.strokeStyle = `hsla(${hue}, ${params.tone.dryness > 0.7 ? 0 : 50}%, ${params.tone.dryness > 0.7 ? 70 : 70}%, ${alpha})`;
ctx.lineWidth = edge.width * (0.5 + 0.5 * pulseProgress);
ctx.beginPath();
ctx.moveTo(a.x, a.y);
ctx.lineTo(b.x, b.y);
ctx.stroke();
});
// Draw nodes
nodes.forEach(node => {
const alpha = Math.min(1, node.energy / node.maxEnergy * 2);
const size = node.size * (0.8 + 0.2 * Math.sin(Date.now() * 0.001 * params.motion));
ctx.fillStyle = node.color + Math.floor(alpha * 255).toString(16).padStart(2, '0') + ')';
ctx.beginPath();
ctx.arc(node.x, node.y, size, 0, Math.PI * 2);
ctx.fill();
});
}
// Animation loop
function animate() {
updateNetwork();
drawNetwork();
requestAnimationFrame(animate);
}
// Start with initial network
initNetwork();
animate();
</script>
</body>
</html>