Boids

Share

群れに指揮者はいない

鳥の群れは、誰かが指示を出しているわけではない。魚の群れも同じ。それぞれが周囲を見て、少しだけ動く。その繰り返しが、全体として秩序ある動きを生む。

これを1986年にCraig Reynoldsがコードで再現した。名前は Boids(bird + oid)。個体に与えるルールは3つだけ。

  1. Separation ── 近すぎたら離れる
  2. Alignment ── 周囲と同じ方向を向く
  3. 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行。


眺めていると

群れは散らばったり、集まったりを繰り返す。たまに渦を巻く。衝突しそうで、しない。

誰も全体を見ていないのに、全体が成り立っている。

みんな思うまま。


参考

Boids (Flocks, Herds, and Schools: a Distributed Behavioral Model)
Background and update on BOIDS, the 1987 model of group motion in flocks, herds, schools and related phenomena. Includes a Java-based demonstration and many links to related research and applications.

Craig Reynolds - Boids

5. Autonomous Agents
So far, I’ve been demonstrating inanimate objects, lifeless shapes sitting on the canvas that flop around when affected by forces in their environment

Nature of Code - Flocking

Read more

Dependabotの対応が面倒なのでRenovateを導入する

Dependabotくんはある程度の依存関係の更新を通知してくれるが、山のようにprojectを抱えているとなんとも痒いところに手が届かない。 ということで、Renovateを使ってみる。 Build software better, togetherGitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.GitHub ここからGitHub Appを入れる。 あとは、指示に従ってポチポチするだけで、超かんたんだった。 感想 自動化最高。

By Sakashita Yasunobu

nodejsのバグを見つけたのでPRを投げてみた

概要 要するに、node --testで特定のバイナリを標準出力に書くと、テストランナーが固まったり、異常終了したりするバグです。 バグ自体は既知のものだったようで、修正がされていました。 test_runner: infinite loop in FileTest#drainRawBuffer when child stdout contains FF 0F followed by large size bytes · Issue #62693 · nodejs/nodeVersion v25.9.0 (also reproduced on v24.14.1 LTS, v22.21.0 LTS, v23.4.0) Platform Darwin 25.

By Sakashita Yasunobu
青空文庫のParser

青空文庫のParser

青空文庫のParserを作ってます。 GitHub - P4suta/aozora: Pure-functional Rust parser for 青空文庫記法 (Aozora Bunko notation): ルビ, 傍点, 縦中横, 外字, 返り点, indent containers, page breaks.Pure-functional Rust parser for 青空文庫記法 (Aozora Bunko notation): ルビ, 傍点, 縦中横, 外字, 返り点, indent containers, page breaks. - P4suta/aozoraGitHubP4suta Rustで作ってますが、配布物はcargoのほかにnpm/pypiでも入手できます Documentation * Playground — try it in

By Sakashita Yasunobu