birth: Branching pathways in hushed code
This commit is contained in:
parent
1a2cf542bd
commit
e77d2ca2e2
1 changed files with 170 additions and 0 deletions
170
index.html
Normal file
170
index.html
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Neurameba · Motd.social</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
background-color: #0a0a0a;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
#attribution {
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
color: #555;
|
||||
font-size: 10px;
|
||||
z-index: 100;
|
||||
}
|
||||
</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;
|
||||
}
|
||||
resizeCanvas();
|
||||
window.addEventListener('resize', resizeCanvas);
|
||||
|
||||
// Parameters from prompt
|
||||
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: {
|
||||
anger: 0.0,
|
||||
sadness: 0.0,
|
||||
curiosity: 0.2,
|
||||
dryness: 0.8,
|
||||
playfulness: 0.0,
|
||||
tension: 0.0
|
||||
}
|
||||
};
|
||||
|
||||
// L-system basics
|
||||
let axiom = "A";
|
||||
const rules = {
|
||||
A: "F+F--F+F",
|
||||
F: "F+F--F+F"
|
||||
};
|
||||
let iterations = 5;
|
||||
let angle = 25 * params.complexity;
|
||||
let length = 20 * (1 - params.density);
|
||||
let maxDepth = 10;
|
||||
let generation = 0;
|
||||
let positions = [];
|
||||
let currentPath = [];
|
||||
let fadeAmount = 0.97;
|
||||
let maxPaths = 20;
|
||||
let paths = [];
|
||||
|
||||
// Color based on tone
|
||||
function getColor() {
|
||||
const dryness = params.tone.dryness;
|
||||
const curiosity = params.tone.curiosity;
|
||||
const mix = dryness * 0.8 + curiosity * 0.2;
|
||||
const hue = mix * 60; // teal range
|
||||
const sat = mix * 0.6 + 0.3; // moderate saturation
|
||||
const light = 0.1 + mix * 0.2; // dark base
|
||||
|
||||
return `hsl(${hue}, ${sat * 100}%, ${light * 100}%)`;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
ctx.fillStyle = 'rgba(0, 0, 0, ' + fadeAmount + ')';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
const color = getColor();
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 1;
|
||||
|
||||
// Add new path occasionally
|
||||
if (paths.length < maxPaths && Math.random() < params.motion * 0.02) {
|
||||
paths.push({
|
||||
points: [],
|
||||
age: 0,
|
||||
maxAge: 100 + Math.random() * 100
|
||||
});
|
||||
}
|
||||
|
||||
// Update and draw paths
|
||||
for (let i = paths.length - 1; i >= 0; i--) {
|
||||
const path = paths[i];
|
||||
|
||||
// Update with L-system growth
|
||||
if (path.age < path.maxAge) {
|
||||
if (path.points.length === 0) {
|
||||
// Start new path
|
||||
path.points.push({x: canvas.width/2, y: canvas.height/2});
|
||||
} else {
|
||||
const last = path.points[path.points.length - 1];
|
||||
const angleVariation = (Math.random() - 0.5) * 20 * params.motion;
|
||||
const newAngle = angle * (1 + angleVariation/100);
|
||||
const newX = last.x + Math.cos(newAngle * Math.PI/180) * length * params.density;
|
||||
const newY = last.y + Math.sin(newAngle * Math.PI/180) * length * params.density;
|
||||
|
||||
// Apply small pulse variation
|
||||
const pulse = params.pulse.avg + (Math.random() - 0.5) * (params.pulse.max - params.pulse.min);
|
||||
length = 20 * (1 - params.density) * pulse;
|
||||
|
||||
path.points.push({x: newX, y: newY});
|
||||
}
|
||||
path.age++;
|
||||
} else {
|
||||
paths.splice(i, 1);
|
||||
}
|
||||
|
||||
// Draw path
|
||||
if (path.points.length > 1) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(path.points[0].x, path.points[0].y);
|
||||
for (let j = 1; j < path.points.length; j++) {
|
||||
ctx.lineTo(path.points[j].x, path.points[j].y);
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
// Occasionally mutate the L-system rules
|
||||
if (Math.random() < 0.01) {
|
||||
const ruleKeys = Object.keys(rules);
|
||||
if (ruleKeys.length > 0) {
|
||||
const key = ruleKeys[Math.floor(Math.random() * ruleKeys.length)];
|
||||
const symbols = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
const newSymbol = symbols[Math.floor(Math.random() * symbols.length)];
|
||||
rules[key] = rules[key].replace(/[A-Z]/g, newSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
// Occasionally change axiom
|
||||
if (Math.random() < 0.005) {
|
||||
axiom = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[Math.floor(Math.random() * 26)];
|
||||
}
|
||||
|
||||
// Occasionally change angle
|
||||
if (Math.random() < 0.005) {
|
||||
angle = 10 + Math.random() * 50;
|
||||
}
|
||||
}
|
||||
|
||||
function animate() {
|
||||
draw();
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
animate();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Reference in a new issue