足元の向きに従う
力の出どころを場に置く。平面のどこに立っても、その場所ごとに「こっちへ」という向きが一つ決まっている。点はその足元の向きへ進み、進んだ先でまた向きを読む。向きを返す場をたどる動きがフロー。
ベクトル場(フロー)。向きを返す場で、各点に矢印が立っていて、その矢印に沿って進む点の軌跡が流線になる。塗る場は (x, y) → 値 の静的な関数だが、その値を進行方向として読むと、点が位置を状態に持って動くエージェントの系に渡せる。angle(x, y) の中身を入れ替えると、同じ歩かせ方のまま流れの形が丸ごと変わる。
場の向きは angle(x, y) が決める。sin と cos を足して π を掛け、-2π〜2π の角度を返す。格子点ごとにその角度の向きへ短い矢印を引くと、画面いっぱいに向きの分布が立つ。x と y をそれぞれ独立に刻んで、全面に格子を張る。
隣り合う矢印の向きが緩く揃って、画面全体に渦や流れの筋が浮かぶ。同じ角度を drift で少しずつ回すと、向きの分布ごと回る。0.012 を上げると向きの変化が細かくなり、矢印が短い間隔で回る。
この矢印の上を点に歩かせる。一粒の足元で angle を読み、cos a を横の進み、sin a を縦の進みに分けて足すと、点が矢印の向きへ一歩進む。それを毎フレーム繰り返すと、通り道が場の流れをなぞる曲線になる。
撒いた点が向きの筋に沿って流れ、通り道が薄く積もって場の形が線で浮かぶ。半透明の paper を毎フレーム上から塗っているので、古い跡が少しずつ消えて尾を引く。点が画面の外へ出たら別の場所へ撒き直して、消えた粒を補う。angle の中身を距離場やノイズに差し替えると、同じ歩かせ方のまま別の流れになる。
毎フレーム場を読み直して angle を計算するのは、点が多いと重い。歩く先が決まっているなら、向きを先に格子へ焼いておく手がある。ゴールのマスを 0 として、そこから幅優先で外へ距離を伸ばし、各マスに「より近いマスを指す向き」を一度だけ書き込む。あとは点がその矢印を読むだけで、壁を回り込んでゴールへ集まる。
フローフィールド。ゴールから幅優先探索(BFS)で距離を測り、各マスに勾配の下る向きを焼いたもの。一度の探索で全マスの向きが決まるので、何体の点が動いても探索は一回で済む。生成アートのベクトル場の歩かせ方が、そのままゲームの群衆ナビに渡る接点になる。
格子の各マスに壁を撒き、ゴールから BFS で距離を広げる。距離が下る向き (fdx, fdy) を矢印で描き、点はその矢印に沿って進む。ゴールに着いた点は別のマスへ撒き直す。
矢印が一斉にゴール(暗い四角)を指して、点がその向きを伝って壁(薄い四角)を回り込み吸い込まれる。BFS は最初の一回だけで、あとは点がマスの向きを読むだけ。Math.random() < 0.16 の壁の密度を上げると迷路が複雑になり、点の回り道が長くなる。撒く点の数を増やしても、向きは焼き済みなので一体ぶんの読み取りが増えるだけになる。