Skip to main content
Artificial Life Flocking Simulation (Boids) new

Flocking Simulation (Boids)

Emergent collective behavior from three simple rules

Controls
Behavior
Effects

The Boids Algorithm

Developed by Craig Reynolds in 1986, Boids simulates the flocking behavior of birds using three simple steering rules applied to each individual agent.

The Three Rules:

  • Separation: Steer to avoid crowding nearby flockmates. Each boid maintains minimum distance from neighbors to prevent collisions.
  • Alignment: Steer towards the average heading of nearby flockmates. Boids match their velocity with their neighbors.
  • Cohesion: Steer towards the average position of nearby flockmates. Boids move toward the center of mass of their local group.

Emergent Behavior: Despite these simple rules operating locally, complex global patterns emerge: coordinated flocking, splitting and merging groups, obstacle avoidance, and predator evasion.

Parameters:

  • Perception Radius: How far each boid can “see” its neighbors
  • Max Speed / Max Force: Limits on velocity and steering acceleration
  • Rule Weights: Relative influence of separation, alignment, and cohesion
© 2013 - 2026 Cylian 🤖 Claude
Instructions Claude

Prompt utilise pour regenerer cette page :

Page: Flocking Simulation (Boids)
Description: "Emergent collective behavior from three simple rules"
Category: artificial-life
Icon: bird
Tags: boids, flocking, emergence, simulation
Status: new

Front matter (index.md):
  title: "Flocking Simulation (Boids)"
  description: "Emergent collective behavior from three simple rules"
  icon: "bird"
  tags: ["boids", "flocking", "emergence", "simulation"]
  status: ["new"]

HTML structure (index.md):
  <section class="container visual size-800 ratio-1-1 canvas-contain">
    <canvas id="boids-canvas"></canvas>
  </section>

Widget files:
- _controls.right.md (weight: 10): ##### Controls
  <div class="boids-controls">
    <div class="boids-actions">
      {{< button id="btn-start" label="Start" class="is-start" >}}
      {{< button id="btn-pause" label="Pause" class="is-pause" >}}
      {{< button id="btn-reset" label="Reset" >}}
    </div>
  </div>

- _options.right.md (weight: 20): Two sections:
  ##### Behavior — <div class="boids-options"> with 5 control-groups:
    - Speed: span#speed-value(4), range#opt-speed min=1 max=10 value=4 step=0.5
    - Separation: span#separation-value(1.5), range#opt-separation min=0 max=3 value=1.5 step=0.1
    - Alignment: span#alignment-value(1.0), range#opt-alignment min=0 max=3 value=1.0 step=0.1
    - Cohesion: span#cohesion-value(1.0), range#opt-cohesion min=0 max=3 value=1.0 step=0.1
    - Flock Size: span#flock-value(100), range#opt-flock min=10 max=300 value=100 step=10
  ##### Effects — <div class="boids-options"> with 4 checkbox control-groups:
    - checkbox#opt-trails: Trails
    - checkbox#opt-predator: Predator (mouse)
    - checkbox#opt-obstacles: Obstacles
    - checkbox#opt-species: Multiple Species

- _algorithm.after.md (no weight specified): Explains Craig Reynolds' 1986 Boids algorithm. Three rules: separation (avoid crowding), alignment (match heading), cohesion (move toward center). Emergent behavior. Parameters: perception radius, max speed/force, rule weights.

Architecture (single file default.js):
  IIFE, no imports (uses console.log)

  CONFIG object:
    flockSize=100, perceptionRadius=50, separationRadius=25, maxSpeed=4, maxForce=0.1
    separationWeight=1.5, alignmentWeight=1.0, cohesionWeight=1.0, boidSize=8
    trailEnabled=false, predatorEnabled=false, obstaclesEnabled=false
    speciesEnabled=false, speciesCount=3

  SPECIES_COLORS: [{hue:200, name:'blue'}, {hue:120, name:'green'}, {hue:30, name:'orange'}]

  State: canvas, ctx, dpr, boids[], predator (Vector2D|null), obstacles[], isRunning, animationId
  cachedColors: {surface:'#fff', primary:'#3498db', text:'#333', predator:'#e74c3c'}

  Vector2D class (full 2D vector math):
    constructor(x=0, y=0)
    Instance methods (return this for chaining): add(v), sub(v), mult(n), div(n), normalize(), limit(max), setMag(n)
    Instance methods (return value): mag(), heading() (atan2), dist(v), copy()
    Static methods: fromAngle(angle), random(mag=1), sub(a, b) returns new Vector2D

  Boid class:
    constructor(x, y, species=0): position (Vector2D), velocity (random at 0.5*maxSpeed), acceleration (zero). Species and hue: if speciesEnabled, uses SPECIES_COLORS[species%3].hue +/- 10 random. Otherwise random 180-240 (blue-cyan range).
    applyForce(force): adds to acceleration.
    getNeighbors(flock, radius): returns boids within radius (excluding self).
    separation(neighbors): steers away from neighbors within separationRadius(25). Diff vector normalized, weighted by 1/distance. Average, setMag(maxSpeed), subtract velocity, limit(maxForce). Returns steering vector.
    alignment(neighbors): average velocity of neighbors. setMag(maxSpeed), subtract velocity, limit(maxForce). Returns steering vector.
    cohesion(neighbors): average position of neighbors. Subtract own position (steer toward center). setMag(maxSpeed), subtract velocity, limit(maxForce). Returns steering vector.
    flee(predatorPos): if within 2x perceptionRadius, steer away at 1.5x maxSpeed, limit 2x maxForce.
    avoidObstacles(obstacleList): for each obstacle, if within obs.radius + perceptionRadius, diff vector normalized/inverse distance. setMag(maxSpeed), limit 2x maxForce.
    flock(flock): get neighbors (filtered by species if enabled). Calculate sep/ali/coh forces with weights. Add predator flee (2x multiplier). Add obstacle avoidance (2x multiplier).
    update(width, height): velocity += acceleration, limit(maxSpeed). position += velocity. Reset acceleration. Wrap edges (toroidal).
    draw(ctx): rotated triangle at velocity heading. size=boidSize(8). Color: HSL(hue, 70%, lightness) where lightness = 40 + speedRatio*20. Triangle: nose at +size, wings at -0.6*size +/-0.5*size, tail indent at -0.4*size.

  Helper functions:
    cacheColors(): reads --background-color-surface, --draw-color-primary, --text-color-surface from CSS. Called on init + theme change.
    initCanvas(): 800x800 logical, multiplied by dpr. ctx.setTransform(dpr) for HiDPI.
    getWidth()/getHeight(): canvas buffer / dpr.
    createFlock(): CONFIG.flockSize boids at random positions. Species assigned round-robin (i % speciesCount) if enabled.
    createObstacles(): 5 obstacles at random positions (10%-90% range), radius 20-50px.

  UI:
    toggleRun(): toggles isRunning, .is-running on .boids-controls. Starts run() or cancels animation.
    updateValueDisplay(id, value): sets element textContent.
    setupUI(): btn-start (start if not running), btn-pause (pause if running), btn-reset (reset). Sliders: opt-speed -> maxSpeed, opt-separation -> separationWeight, opt-alignment -> alignmentWeight, opt-cohesion -> cohesionWeight, opt-flock -> flockSize (triggers createFlock). Checkboxes: opt-trails -> trailEnabled, opt-predator -> predatorEnabled (clears predator on uncheck), opt-obstacles -> obstaclesEnabled (creates/clears obstacles), opt-species -> speciesEnabled (triggers createFlock).

  Mouse events:
    handleCanvasClick(e): if predator enabled, places predator at click position. Auto-clears after 3s (setTimeout).
    handleMouseMove(e): if predator enabled, continuously tracks mouse as predator position.
    handleMouseLeave(): clears predator.

  Simulation:
    run(): if not running return. For each boid: flock(boids). For each boid: update(width, height). draw(). requestAnimationFrame(run).
    draw(): trail mode: semi-transparent fill (alpha=0.1) instead of full clear. Draw all boids. Draw obstacles (gray semi-transparent circles with border). Draw predator (red dot radius 15 + perception circle at 2x radius, alpha 0.2).
    reset(): clears predator, createFlock, draw.

  Initialization:
    init(): gets boids-canvas, 2d context. cacheColors, theme change listener. initCanvas. setupUI. Canvas mouse events (click, mousemove, mouseleave). createFlock. AUTO-STARTS (isRunning=true, adds .is-running, calls run()).
    Auto-init: readyState check, DOMContentLoaded fallback.

SCSS file (default.scss):
  :root CSS custom properties:
    --boids-color-separation: var(--color-red)
    --boids-color-alignment: var(--color-blue)
    --boids-color-cohesion: var(--color-green)
    --boids-color-predator: var(--color-red)

  $breakpoint-mobile: 768px

  layout-main scope:
    main: flex column centered, padding 2rem, gap 1.5rem
    #boids-canvas: 100% width/height, 1px solid border (draw-color-surface), 4px radius, surface bg, cursor crosshair

  @media mobile: main padding 1rem, gap 1rem

  .boids-legend: flex column, gap 0.5rem. &.inline: row wrap, gap 1rem.
    .legend-item: inline-flex row, align center, gap 0.25rem, weight 300, surface text
    .swatch: 0.75rem circle. &.separation/alignment/cohesion: colored by CSS vars.

  .boids-controls:
    .boids-actions: flex row nowrap, justify center, gap 0.5rem
    .is-start: display inline-flex (visible)
    .is-pause: display none (hidden)
    &.is-running: .is-start none, .is-pause inline-flex

  .boids-options: flex column, gap 0.75rem
    .control-group: flex column, gap 0.25rem
      label: 0.85rem, weight 400, surface text
      input[type="range"]: 100% width, pointer
      &.checkbox: flex row, align center
        label: flex row, align center, gap 0.5rem, pointer
        input[type="checkbox"]: pointer

Page entierement generee et maintenue par IA, sans intervention humaine.