Boids
群れに指揮者はいない
鳥の群れは、誰かが指示を出しているわけではない。魚の群れも同じ。それぞれが周囲を見て、少しだけ動く。その繰り返しが、全体として秩序ある動きを生む。
これを1986年にCraig Reynoldsがコードで再現した。名前は Boids(bird + oid)。個体に与えるルールは3つだけ。
- Separation ── 近すぎたら離れる
- Alignment ── 周囲と同じ方向を向く
- Cohesion ── 群れの中心に寄る
これだけで、群れは群れらしく動く。
なぜ作ったか
群れの動きは、見ていて飽きない。
- 単純なルールから複雑な動きが生まれる ── 創発(emergence)の典型例。設計していないのに、設計したかのように見える。
- 自分のブログに置きたかった ── 静的なページに、動くものがあると空気が変わる。
- Web Components で作りたかった ── どこにでも持っていける部品として。
設計の話
見えないときは止める
画面外でアニメーションを回し続けるのは無駄。IntersectionObserver でビューポートを監視し、見えなくなったら停止する。タブを切り替えたときも visibilitychange で止める。
モバイルではバッテリーの問題がある。見えないものに計算資源を使わないのは、礼儀のようなもの。
O(n²) を O(n) に
素朴に実装すると、全個体が全個体をチェックする。80匹で6,400回、500匹で250,000回。
空間ハッシュ(Spatial Hash)を使うと、近傍だけを見れば済む。知覚範囲をセルサイズにして、隣接セルだけを探索する。計算量は個体数に比例するだけになる。
色は oklch()
hsl() は色相によって明るさが変わる。黄色は明るく見え、青は暗く見える。oklch() は知覚的に均一で、hue を変えても明るさが揃う。
--_boid-color: light-dark(
oklch(35% 0.1 var(--boids-hue)),
oklch(85% 0.1 var(--boids-hue))
);
ダークモード対応も light-dark() で1行。
眺めていると
群れは散らばったり、集まったりを繰り返す。たまに渦を巻く。衝突しそうで、しない。
誰も全体を見ていないのに、全体が成り立っている。
みんな思うまま。
参考

Craig Reynolds - Boids

Nature of Code - Flocking
