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.