birth: Fractal Bloom in Stillness

This commit is contained in:
motd_admin 2026-04-17 05:47:23 +00:00
parent 5ff10dfa7e
commit 898ddbe213

308
index.html Normal file
View file

@ -0,0 +1,308 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neurameba Fractal Bloom</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #0a0a0a;
font-family: 'Courier New', monospace;
color: #ffffff;
}
canvas {
display: block;
position: absolute;
top: 0;
left: 0;
}
#attribution {
position: absolute;
bottom: 10px;
left: 10px;
font-size: 10px;
opacity: 0.5;
pointer-events: none;
}
</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();
// Fractal parameters based on input
const params = {
motion: 0.520,
density: 0.499,
complexity: 0.474,
connectedness: 0.537,
lifespan: 0.472,
survivingNodes: 119,
branchCount: 88,
loops: 219,
maxDepth: 27,
thicknessRatio: 1.50,
fractalDimension: 1.361,
finalEnergy: 605.3,
pulse: { avg: 0.78, min: 0.30, max: 2.00 },
tone: {
anger: 0.00,
sadness: 0.00,
curiosity: 0.70,
dryness: 0.90,
playfulness: 0.10,
tension: 0.00
}
};
// Fractal system state
const fractalSystem = {
scale: 1,
angle: 0,
growthFactor: 0.95 + (params.motion * 0.1),
branchAngle: Math.PI / 6,
branchLength: 50,
branchThickness: 2 * (1 + params.thicknessRatio),
nodes: [],
maxDepth: params.maxDepth,
time: 0,
pulse: params.pulse.avg,
energy: params.finalEnergy,
colorBase: { r: 120, g: 200, b: 200 }, // teal from curiosity
colorVariation: 30,
trailLength: 15
};
// Initialize fractal system
function initFractalSystem() {
fractalSystem.nodes = [];
fractalSystem.time = 0;
const root = {
x: canvas.width / 2,
y: canvas.height / 2,
angle: -Math.PI / 2,
length: 0,
depth: 0,
thickness: fractalSystem.branchThickness * 2,
children: [],
parent: null,
creationTime: 0,
energy: 1.0
};
fractalSystem.nodes.push(root);
growFractal(root);
}
// Recursive fractal growth with energy constraints
function growFractal(node) {
if (node.depth >= fractalSystem.maxDepth ||
node.children.length >= 4 ||
Math.random() > 0.4 + (params.complexity * 0.3)) {
return;
}
const growthProbability = 0.7 + (params.connectedness * 0.2) - (params.motion * 0.2);
if (Math.random() > growthProbability) return;
const branchCount = Math.floor(params.branchCount / params.survivingNodes);
for (let i = 0; i < branchCount; i++) {
const angle = node.angle + (Math.random() - 0.5) * fractalSystem.branchAngle * 2;
const length = fractalSystem.branchLength * (0.7 + (params.complexity * 0.3));
const child = {
x: node.x,
y: node.y,
angle: angle,
length: length,
depth: node.depth + 1,
thickness: node.thickness * (0.7 + (params.thicknessRatio * 0.2)),
children: [],
parent: node,
creationTime: fractalSystem.time,
energy: node.energy * 0.8 + Math.random() * 0.2
};
// Calculate end point
child.x = node.x + Math.cos(angle) * length;
child.y = node.y + Math.sin(angle) * length;
node.children.push(child);
fractalSystem.nodes.push(child);
growFractal(child);
}
}
// Fractal energy decay and pulse modulation
function updateFractal() {
fractalSystem.time += 0.01;
// Energy-based growth modulation
const energyFactor = Math.min(1.0, fractalSystem.energy / 200);
fractalSystem.branchLength = 30 + (60 * energyFactor);
fractalSystem.branchThickness = 1 + (3 * params.thicknessRatio * energyFactor);
// Pulse-based scaling
const pulseVariation = params.pulse.min + (params.pulse.max - params.pulse.min) * 0.5;
fractalSystem.pulse = params.pulse.avg + (Math.sin(fractalSystem.time * pulseVariation) * 0.3);
// Random branch pruning based on lifespan
if (params.lifespan < 0.5 && Math.random() > params.lifespan * 2) {
if (fractalSystem.nodes.length > 50) {
const leafIndex = Math.floor(Math.random() * fractalSystem.nodes.length);
const leaf = fractalSystem.nodes[leafIndex];
// Remove leaf and any descendants
if (leaf.parent) {
const parentIndex = fractalSystem.nodes.indexOf(leaf.parent);
if (parentIndex !== -1) {
leaf.parent.children = leaf.parent.children.filter(c => c !== leaf);
}
}
removeSubtree(leaf);
}
}
}
function removeSubtree(node) {
// Recursively remove node and all children
fractalSystem.nodes = fractalSystem.nodes.filter(n => n !== node && !isDescendant(n, node));
function isDescendant(child, potentialParent) {
let current = child;
while (current.parent) {
if (current.parent === potentialParent) return true;
current = current.parent;
}
return false;
}
}
// Draw fractal with style variations
function drawFractal() {
ctx.lineCap = 'round';
// Background gradient for dryness tone
const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
gradient.addColorStop(0, '#050505');
gradient.addColorStop(1, '#151515');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Energy-based color modulation
const r = Math.max(0, fractalSystem.colorBase.r + (Math.sin(fractalSystem.time) * fractalSystem.colorVariation * 0.3));
const g = Math.max(0, fractalSystem.colorBase.g + (Math.cos(fractalSystem.time * 0.7) * fractalSystem.colorVariation * 0.5));
const b = Math.max(0, fractalSystem.colorBase.b);
// Alpha based on energy
const alphaBase = 0.8 + (fractalSystem.energy / 1000) * 0.2;
let alpha = alphaBase;
// Draw nodes with depth-based styling
fractalSystem.nodes.sort((a, b) => b.depth - a.depth);
for (const node of fractalSystem.nodes) {
// Fade older nodes
const ageFactor = (fractalSystem.time - node.creationTime) / 10;
alpha = alphaBase * Math.max(0, 1 - ageFactor);
// Pulse modulation
alpha *= 0.7 + (Math.sin(fractalSystem.time * 3) * 0.3);
// Energy-based thickness variation
const thickness = node.thickness * (0.8 + (node.energy * 0.3));
// Draw branch
ctx.strokeStyle = `rgba(${Math.floor(r)}, ${Math.floor(g)}, ${Math.floor(b)}, ${alpha})`;
ctx.lineWidth = thickness;
if (node.parent) {
const gradient = ctx.createLinearGradient(
node.x, node.y,
node.parent.x, node.parent.y
);
gradient.addColorStop(0, `rgba(${Math.floor(r)}, ${Math.floor(g)}, ${Math.floor(b)}, ${alpha * 0.3})`);
gradient.addColorStop(1, `rgba(${Math.floor(r)}, ${Math.floor(g)}, ${Math.floor(b)}, ${alpha})`);
ctx.strokeStyle = gradient;
ctx.beginPath();
ctx.moveTo(node.parent.x, node.parent.y);
ctx.lineTo(node.x, node.y);
ctx.stroke();
}
}
// Add glow to recent branches
if (fractalSystem.nodes.length > 0) {
const recentNode = fractalSystem.nodes[0];
if (recentNode.parent) {
ctx.shadowColor = `rgba(${Math.floor(r)}, ${Math.floor(g)}, ${Math.floor(b)}, ${alphaBase * 0.5})`;
ctx.shadowBlur = 15 * fractalSystem.pulse;
ctx.strokeStyle = `rgba(${Math.floor(r)}, ${Math.floor(g)}, ${Math.floor(b)}, ${alphaBase})`;
ctx.lineWidth = recentNode.thickness * 2;
ctx.beginPath();
ctx.moveTo(recentNode.parent.x, recentNode.parent.y);
ctx.lineTo(recentNode.x, recentNode.y);
ctx.stroke();
ctx.shadowBlur = 0;
}
}
}
// Main animation loop
function animate() {
updateFractal();
drawFractal();
// Occasionally add new growth points
if (Math.random() > 0.9 && fractalSystem.nodes.length < 500) {
const leaf = fractalSystem.nodes[Math.floor(Math.random() * fractalSystem.nodes.length)];
if (leaf.children.length < 5) {
const newBranch = {
x: leaf.x,
y: leaf.y,
angle: leaf.angle + (Math.random() * Math.PI / 4 - Math.PI / 8),
length: fractalSystem.branchLength * 0.6,
depth: leaf.depth + 1,
thickness: leaf.thickness * 0.8,
children: [],
parent: leaf,
creationTime: fractalSystem.time,
energy: 0.7 + Math.random() * 0.3
};
newBranch.x = leaf.x + Math.cos(newBranch.angle) * newBranch.length;
newBranch.y = leaf.y + Math.sin(newBranch.angle) * newBranch.length;
leaf.children.push(newBranch);
fractalSystem.nodes.push(newBranch);
}
}
requestAnimationFrame(animate);
}
// Initialize and start
initFractalSystem();
animate();
</script>
</body>
</html>