Flocking Birds - Boids Algorithm - xelsed.ai

45 views Β· Dec 10, 2025

Mesmerizing flocking simulation using the classic boids algorithm. 100 birds follow three simple rules: separation, alignment, and cohesion - yet together they create beautiful emergent swarm behavior. Watch them naturally form flocks and swirl across a serene sky gradient.

#boids#flocking#birds#simulation#emergent#swarm#xelsedia#xelsedai#xelsedp5flashalpha02
πŸ”€ Remix This πŸ“– View Docs β›Ά Full Screen ← Back to Gallery
πŸ“‹ Embed Code

Copy this code to embed this sketch on your website:

<iframe src="https://p5js.ai/embed/67494453-e372-48bd-94c5-6021961fbf4d" width="400" height="400" frameborder="0" allow="autoplay" title="Flocking Birds - Boids Algorithm - xelsed.ai"></iframe>

Adjust width and height as needed. Preview embed β†’

❓ About This Sketch 3 questions

What visual experience does the Flocking Birds sketch create?

The sketch visually simulates a flock of 100 birds that gracefully swarm and swirl across a serene sky gradient, showcasing emergent behavior through the boids algorithm.

How can users interact with the Flocking Birds simulation?

Users can interact by resizing the window, which will dynamically adjust the canvas and sky gradient to maintain the immersive experience.

What creative coding concept is demonstrated in the Flocking Birds sketch?

This sketch demonstrates the boids algorithm, which uses simple rules of separation, alignment, and cohesion to create complex, natural flocking behavior.

πŸ’¬ AI Chat History 2 messages
πŸ‘€ You
Create a flocking simulation using the boids algorithm. 100 small triangular birds that fly together following three rules: separation (avoid crowding), alignment (steer towards average heading), and cohesion (steer towards center of flock). Birds should wrap around screen edges. Add slight trail effect. Use white/gray birds on a sky blue gradient background. Birds should naturally form flocks and swirl around.
πŸ€– AI
Here’s a complete boids flocking sketch with 100 triangular β€œbirds”, edge wrapping, and a subtle trail over a sky blue gradient.

---

### `index.html`

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Boids Flocking - p5.js</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- p5.js core library -->
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/p5.min.js"></script>

<!-- Your sketch -->
<script src="sketch.js"></script>
</body>
</html>
```

---

### `style.css`

```css
body {
margin: 0;
padding: 0;
overflow: hidden;
background: #6fb6ff; /* fallback if canvas doesn't load */
font-family: sans-serif;
}

canvas {
display: block;
}
```

---

### `sketch.js`

```js
// Boids flocking simulation
// Uses p5.js 1.11.3
// Key APIs: createVector, p5.Vector.heading, tint, image, createGraphics, resizeCanvas
// Docs: https://p5js.org/reference/

let boids = [];
const NUM_BOIDS = 100;

// Off-screen graphics for the sky gradient
let skyGraphic;

// Trail strength (0–255): lower = longer trails
const TRAIL_ALPHA = 40;

function setup() {
createCanvas(windowWidth, windowHeight);

// Create sky gradient once
skyGraphic = createGraphics(windowWidth, windowHeight);
drawSkyGradient(skyGraphic);

// Initialize flock
for (let i = 0; i < NUM_BOIDS; i++) {
boids.push(new Boid());
}

// Smoother visuals
frameRate(60);
}

function draw() {
// Draw the sky gradient with some transparency to create a trail effect
tint(255, TRAIL_ALPHA);
image(skyGraphic, 0, 0, width, height);
noTint(); // Reset so boids are drawn normally

// Update and render all boids
for (let boid of boids) {
boid.edges();
boid.flock(boids);
boid.update();
boid.show();
}
}

// Recreate canvas and gradient on window resize
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
skyGraphic = createGraphics(windowWidth, windowHeight);
drawSkyGradient(skyGraphic);
}

// Draw a vertical sky blue gradient into a p5.Graphics buffer
function drawSkyGradient(pg) {
pg.noFill();
const topColor = pg.color(170, 220, 255); // light blue
const bottomColor = pg.color(30, 120, 200); // deeper blue

for (let y = 0; y < pg.height; y++) {
const t = y / (pg.height - 1 || 1);
const c = pg.lerpColor(topColor, bottomColor, t);
pg.stroke(c);
pg.line(0, y, pg.width, y);
}
}

/* =======================
Boid class
======================= */

class Boid {
constructor() {
this.position = createVector(random(width), random(height));

// Random initial direction & speed
const angle = random(TWO_PI);
this.velocity = p5.Vector.fromAngle(angle);
this.velocity.setMag(random(1, 2));

this.acceleration = createVector();

this.maxSpeed = 2.5;
this.maxForce = 0.05;

this.size = 6; // base size for the triangle

// White/gray birds
const brightness = random(210, 255);
this.bodyColor = color(brightness);
this.strokeColor = color(brightness * 0.8);
}

// Wrap around screen edges
edges() {
const margin = this.size * 2;

if (this.position.x > width + margin) {
this.position.x = -margin;
} else if (this.position.x < -margin) {
this.position.x = width + margin;
}

if (this.position.y > height + margin) {
this.position.y = -margin;
} else if (this.position.y < -margin) {
this.position.y = height + margin;
}
}

// Main flocking behavior: apply separation, alignment, and cohesion
flock(boids) {
const alignment = this.align(boids);
const cohesion = this.cohesion(boids);
const separation = this.separation(boids);

// Weight the three behaviors
alignment.mult(1.0);
cohesion.mult(1.0);
separation.mult(1.5);

this.acceleration.add(alignment);
this.acceleration.add(cohesion);
this.acceleration.add(separation);
}

// Alignment: steer towards the average heading of local flockmates
align(boids) {
const perceptionRadius = 60;
const steering = createVector();
let total = 0;

for (let other of boids) {
const d = dist(
this.position.x,
this.position.y,
other.position.x,
other.position.y
);
if (other !== this && d < perceptionRadius) {
steering.add(other.velocity);
total++;
}
}

if (total > 0) {
steering.div(total);
steering.setMag(this.maxSpeed);
steering.sub(this.velocity);
steering.limit(this.maxForce);
}

return steering;
}

// Cohesion: steer towards the center of mass of local flockmates
cohesion(boids) {
const perceptionRadius = 65;
const steering = createVector();
let total = 0;

for (let other of boids) {
const d = dist(
this.position.x,
this.position.y,
other.position.x,
other.position.y
);
if (other !== this && d < perceptionRadius) {
steering.add(other.position);
total++;
}
}

if (total > 0) {
steering.div(total);
steering.sub(this.position); // vector towards center
steering.setMag(this.maxSpeed);
steering.sub(this.velocity);
steering.limit(this.maxForce);
}

return steering;
}

// Separation: avoid crowding – steer away from neighbors that are too close
separation(boids) {
const perceptionRadius = 30;
const steering = createVector();
let total = 0;

for (let other of boids) {
const d = dist(
this.position.x,
this.position.y,
other.position.x,
other.position.y
);
if (other !== this && d < perceptionRadius && d > 0) {
// Vector pointing away, weighted by distance
const diff = p5.Vector.sub(this.position, other.position);
diff.div(d * d); // stronger repulsion when very close
steering.add(diff);
total++;
}
}

if (total > 0) {
steering.div(total);
steering.setMag(this.maxSpeed);
steering.sub(this.velocity);
steering.limit(this.maxForce * 1.2);
}

return steering;
}

update() {
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxSpeed);
this.position.add(this.velocity);
// Reset acceleration each frame
this.acceleration.mult(0);
}

// Draw a small triangle pointing in the direction of travel
show() {
push();
translate(this.position.x, this.position.y);

// Rotate so the triangle points along the velocity vector
const angle = this.velocity.heading() + PI / 2;
rotate(angle);

stroke(this.strokeColor);
strokeWeight(1);
fill(this.bodyColor);

// Triangle pointing "forward" (upward before rotation)
beginShape();
vertex(0, -this.size * 2); // tip
vertex(-this.size, this.size*2);
vertex(this.size, this.size*2);
endShape(CLOSE);

pop();
}
}
```

---

You can tweak behavior by adjusting:

- `NUM_BOIDS` (more or fewer birds)
- `TRAIL_ALPHA` (lower = longer trails, e.g. 30; higher = shorter trails, e.g. 80)
- `maxSpeed`, `maxForce`, and the weights for `alignment`, `cohesion`, `separation` in `flock()`.

If you’d like, I can add controls (e.g., dat.GUI) to adjust these parameters live.
🎬 Video Preview