// 031 - L-System Fractal Tree (botany)
// 1:1 Original algorithm engine source
function createFractalTree() {
function drawBranch(ctx, x, y, length, angle, depth, branchRatio, wind, time) {
if (depth <= 0) {
const leafHue = (110 + Math.sin(time + x * 0.01) * 30) % 360;
ctx.fillStyle = hsla(leafHue, 85, 60, 0.85);
ctx.beginPath();
ctx.arc(x, y, 3.5, 0, Math.PI * 2);
ctx.fill();
return;
}
const endX = x + Math.cos(angle) * length;
const endY = y + Math.sin(angle) * length;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(endX, endY);
const branchHue = depth > 5 ? 30 : 90 + depth * 8;
ctx.strokeStyle = hsla(branchHue, 75, depth > 5 ? 35 : 55, 0.9);
ctx.lineWidth = Math.max(1, depth * 1.5);
ctx.stroke();
const branchAngle = 0.42 + wind * 0.15;
const nextLen = length * branchRatio;
drawBranch(ctx, endX, endY, nextLen, angle - branchAngle + wind * 0.08, depth - 1, branchRatio, wind, time);
drawBranch(ctx, endX, endY, nextLen, angle + branchAngle + wind * 0.08, depth - 1, branchRatio, wind, time);
}
return {
setup() {
},
render(context, timeState, params) {
const { ctx, width, height } = context;
const depth = Math.min(9, Number(params.branchDepth || 8));
const branchRatio = Number(params.branchRatio || 0.72);
const windSpeed = Number(params.windSpeed || 1.2);
const t = timeState.time * windSpeed;
ctx.fillStyle = "#06090c";
ctx.fillRect(0, 0, width, height);
const trunkX = width * 0.5;
const trunkY = height * 0.92;
const trunkLength = height * 0.22;
const wind = Math.sin(t * 1.8) * 0.35 + Math.sin(t * 0.7) * 0.2;
drawBranch(ctx, trunkX, trunkY, trunkLength, -Math.PI / 2, depth, branchRatio, wind, t);
}
};
}
// Default parameters from content metadata
const defaultParams = [
{
"key": "branchDepth",
"label": "Recursion Depth",
"type": "range",
"min": 4,
"max": 9,
"step": 1,
"defaultValue": 8,
"description": "Branching recursion levels"
},
{
"key": "branchRatio",
"label": "Branch Length Ratio",
"type": "range",
"min": 0.55,
"max": 0.85,
"step": 0.02,
"defaultValue": 0.72,
"description": "Child branch scaling factor"
},
{
"key": "windSpeed",
"label": "Wind Gust Turbulence",
"type": "range",
"min": 0.2,
"max": 2.5,
"step": 0.1,
"defaultValue": 1.2,
"description": "Harmonic wind velocity"
}
];
if (!window.__art_instances) window.__art_instances = {};
if (!window.__art_instances['fractal-tree']) {
const inst = typeof createFractalTree === 'function' ? createFractalTree() : null;
if (inst && inst.setup) {
inst.setup({ ctx, width, height, dpr: 1, aspectRatio: width / height }, defaultParams);
}
window.__art_instances['fractal-tree'] = inst;
}
const instance = window.__art_instances['fractal-tree'];
if (instance && instance.render) {
instance.render(
{ ctx, width, height, dpr: 1, aspectRatio: width / height },
{ time, deltaTime: dt, frameCount: Math.floor(time * 60), fps: 60 },
defaultParams
);
}