This project is inspired by murmuration by robert hodgin. It merges algorithmic plant growth with flocking mechanics. The project transitions particles between a structured tree form and a chaotic swarm. I also took inspiration from the reinforcement learning process which is where the idea of generations comes from.
I started by defining the base entity. I created the Boid class then I gave each boid standard steering behaviors. These include separate and align then I added the cohere function. These functions calculate vectors. The boids avoid crowding instead they match velocities with neighbors. Next, I tackled the structural element. I wrote a recursive function named genPts. This function calculates coordinates for a branching fractal tree. The function takes arguments for position and angle then it processes length and depth and it calculates segments using trigonometry. It pushes vectors into a global treePts array but I needed a system to alternate between the two behaviors so I implemented a time-based state machine inside the draw loop. Phase zero represents the growth phase. Boids use an arrive steering behavior to settle into specific coordinates along the fractal branches. Phase one represents the swarm phase. The boids break free. They apply flocking rules.
Particles

flocking

fractar tree generation

putting the particles together

the code i am proud of is regenTree function. It manages the visual evolution of the simulation across generations, then it scales the tree depth. It mutates the branching spread angle and dynamically links the boid objects to the newly generated tree points.
// rebuild tree by age/gen
function regenTree(g) {
treePts = [];
// scale depth/len by gen (cap depth 4 fps)
let maxD = min(3 + floor(g / 2), 6);
let baseLen = min(height * 0.12 + g * 12, height * 0.3);
// mut spread by gen
let spread = PI / (5 + sin(g) * 1.5);
genPts(width / 2, height - 30, -PI / 2, baseLen, maxD, spread);
// sync boids to new pts
for (let i = 0; i < treePts.length; i++) {
if (i < boids.length) {
boids[i].treePos = treePts[i].copy(); // assign new tgt
} else {
// spawn new boids at base to sim growth
boids.push(new Boid(width / 2, height, treePts[i]));
}
}
// trim excess (edge case)
if (boids.length > treePts.length) {
boids.splice(treePts.length);
}
}
A specific challenge involved the arrive steering behavior. The boids would overshoot their target coordinates at high velocities. They would oscillate rapidly around the target point. I adjusted the distance threshold mapping by mapping the boid’s speed to decrease linearly when it enters a 100-pixel radius of its assigned treePos. This adjustment solved the jittering issue.
I plan to add interactive elements. Users will click to disrupt the swarm. I want to introduce a wind force variable. This force will push the boids horizontally. I will implement a visual trail system for the boids to emphasize their flight paths.