Boids Emergence
Complex self-organizing flocking dynamics emerging entirely from three simple local rules: alignment, cohesion, and separation.
60 FPS • Canvas 2D
Click + Drag to interact with field
</>
Full Executable Algorithm Code
126 lines
4116 chars
// 012 - Boids Emergence (particles)
// 1:1 Original algorithm engine source
function createBoidsFlocking() {
const MAX_BOIDS = 400;
const px = new Float32Array(MAX_BOIDS);
const py = new Float32Array(MAX_BOIDS);
const vx = new Float32Array(MAX_BOIDS);
const vy = new Float32Array(MAX_BOIDS);
return {
setup(context) {
for (let i = 0; i < MAX_BOIDS; i++) {
px[i] = Math.random() * context.width;
py[i] = Math.random() * context.height;
const a = Math.random() * Math.PI * 2;
vx[i] = Math.cos(a) * 2;
vy[i] = Math.sin(a) * 2;
}
},
render(context, _timeState, params) {
const { ctx, width, height } = context;
const count = Math.min(MAX_BOIDS, Number(params.boidCount || 250));
const visualRange = 45;
const visualRangeSq = visualRange * visualRange;
const minDistance = 14;
const minDistSq = minDistance * minDistance;
const maxSpeed = 3.5;
ctx.fillStyle = "rgba(8, 9, 13, 0.2)";
ctx.fillRect(0, 0, width, height);
for (let i = 0; i < count; i++) {
let alignX = 0;
let alignY = 0;
let cohereX = 0;
let cohereY = 0;
let separateX = 0;
let separateY = 0;
let neighbors = 0;
for (let j = 0; j < count; j++) {
if (i === j) continue;
const dx = px[j] - px[i];
const dy = py[j] - py[i];
const dSq = dx * dx + dy * dy;
if (dSq < visualRangeSq) {
alignX += vx[j];
alignY += vy[j];
cohereX += px[j];
cohereY += py[j];
neighbors++;
if (dSq < minDistSq) {
separateX -= dx / (Math.sqrt(dSq) + 0.1);
separateY -= dy / (Math.sqrt(dSq) + 0.1);
}
}
}
if (neighbors > 0) {
alignX /= neighbors;
alignY /= neighbors;
cohereX = cohereX / neighbors - px[i];
cohereY = cohereY / neighbors - py[i];
vx[i] += alignX * 0.05 + cohereX * 5e-3 + separateX * 0.15;
vy[i] += alignY * 0.05 + cohereY * 5e-3 + separateY * 0.15;
}
const toCenterX = width * 0.5 - px[i];
const toCenterY = height * 0.5 - py[i];
vx[i] += toCenterX * 3e-4;
vy[i] += toCenterY * 3e-4;
const speed = Math.sqrt(vx[i] * vx[i] + vy[i] * vy[i]);
if (speed > maxSpeed) {
vx[i] = vx[i] / speed * maxSpeed;
vy[i] = vy[i] / speed * maxSpeed;
}
px[i] += vx[i];
py[i] += vy[i];
if (px[i] < 0) px[i] += width;
if (px[i] > width) px[i] -= width;
if (py[i] < 0) py[i] += height;
if (py[i] > height) py[i] -= height;
const heading = Math.atan2(vy[i], vx[i]);
const hue = (160 + heading / Math.PI * 90 + 360) % 360;
ctx.save();
ctx.translate(px[i], py[i]);
ctx.rotate(heading);
ctx.fillStyle = hsla(hue, 90, 65, 0.85);
ctx.beginPath();
ctx.moveTo(6, 0);
ctx.lineTo(-4, -3);
ctx.lineTo(-2, 0);
ctx.lineTo(-4, 3);
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
};
}
// Default parameters from content metadata
const defaultParams = [
{
"key": "boidCount",
"label": "Boid Population",
"type": "range",
"min": 50,
"max": 400,
"step": 25,
"defaultValue": 250,
"description": "Total agent count"
}
];
if (!window.__art_instances) window.__art_instances = {};
if (!window.__art_instances['boids-flocking']) {
const inst = typeof createBoidsFlocking === 'function' ? createBoidsFlocking() : null;
if (inst && inst.setup) {
inst.setup({ ctx, width, height, dpr: 1, aspectRatio: width / height }, defaultParams);
}
window.__art_instances['boids-flocking'] = inst;
}
const instance = window.__art_instances['boids-flocking'];
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
);
} Edit in Interactive Playground
Zero Dependencies • Standalone Canvas 2D
ƒ
Mathematical Formulation
high
Analytical Equation
ai=wavalign+wcvcohere+wsvseparate+Fcenter
Click to expand
∑
Boids Emergence
Full Mathematical System • particles
100%
Complete System of Equations
[Governing Law][Discrete Progression][Domain & Space][Parameter State]ai=wavalign+wcvcohere+wsvseparate+Fcenterv+=align⋅0.05+cohere⋅0.005+separate⋅0.15,p+=clamp(v,maxSpeed)x∈R2,t∈R+,ω∈[0,2π]λboidCount=250(Boid Population)
ai=wavalign+wcvcohere+wsvseparate+Fcenter
Computational Implementation (JavaScript Engine Equivalent)
v += align * 0.05 + cohere * 0.005 + separate * 0.15, p += clamp(v, maxSpeed) Compact Formula
v += align * 0.05 + cohere * 0.005 + separate * 0.15, p += clamp(v, maxSpeed) Mathematical Tags
#boids
#flocking
#artificial-life
#emergence
#particles
#vectors
Author: Math Art Core Target: 60 FPS
Press ESC or F to exit