Ollin

Flocking

a few hundred boids, each steering only by its neighbors (separate, align, cohere), so the flock swirls and regroups with no leader (Boids)

Run
swift run --package-path Examples Example-Patterns-Flocking
Source
Examples/Patterns/Flocking/Sketch.swift
import Ollin

/// Flocking: a few hundred boids, each steering only by what its neighbors do,
/// yet the flock as a whole swirls, splits, and regroups with no leader. Every
/// boid follows three local rules, steer away from crowding, match the heading of
/// nearby boids, and drift toward their center, and the coherent motion emerges.
///
/// The boids are drawn as little triangles pointing along their velocity and
/// tinted by heading, so boids traveling the same way share a color and each
/// sub-flock reads as its own band. It's pure simulation, so it never settles.
@main
final class Flocking: Sketch {
    private var flock: Boids?

    override func draw() {
        if flock == nil {
            flock = Boids(count: 520, in: bounds, seed: 7,
                          maxSpeed: 3.4 * scale, maxForce: 0.14 * scale,
                          perceptionRadius: 56 * scale, separationRadius: 26 * scale,
                          margin: 80 * scale)
        }
        guard let flock else { return }
        flock.step()

        background(Color(hex: 0x0E1016))
        noStroke()

        let size = 9 * scale
        for i in 0 ..< flock.count {
            let p = flock.positions[i]
            let a = flock.heading(i)
            fill(Color(hue: (a + .pi) / (2 * .pi), saturation: 0.55, brightness: 0.96))
            let nose = Vector2(p.x + cos(a) * size, p.y + sin(a) * size)
            let left = Vector2(p.x + cos(a + 2.5) * size * 0.7, p.y + sin(a + 2.5) * size * 0.7)
            let right = Vector2(p.x + cos(a - 2.5) * size * 0.7, p.y + sin(a - 2.5) * size * 0.7)
            drawTriangle(nose, left, right)
        }
    }
}

↑↓ move ↩ open