地図/気まぐれ/プロシージャル生成

ナビゲーション — フローフィールド

ゴールを一つ決めて、そこから全マスへ「あと何歩か」を測る。各マスに、ゴールへ一歩近づく隣の向きを矢印として置く。大群のキャラはそれぞれ足元の矢印を辿るだけで、壁を回り込んで一斉にゴールへ集まる。一体ごとに最短路を解かず、距離場を一回焼いて全員で共有する。

フローフィールド(ベクトルフィールドパスファインディング)は、ゴールから幅優先探索で距離場を作り、各マスの勾配を進行方向にした地図。一体ごとに A* を解くと群衆の規模ぶんコストが増えるが、ゴールが一つなら距離場を一度焼くだけで全員ぶんの経路が決まる。RTS の集団移動に使われる。距離の測り方を BFS(一歩=1)からダイクストラ(地形コスト付き)に替えると、沼を避けて道を通る重みつきの流れになる。

ゴールから波を流す。ゴールのマスに歩数 0 を置き、上下左右の隣の床へ一歩ずつ歩数を書き込みながら、まだ未到達の床だけを次の層へ積む。壁にぶつかると波はそこで止まり、壁の裏へは別の経路から回り込む。歩数を明るさに焼くと、ゴール(黒い升)の近くが暗く、遠いほど明るいグラデーションになる。

明るさの段がそのまま、ゴールまでの距離の等高線になる。同じ歩数の床が帯になって、ゴールを囲む輪のように並ぶ。波が回り込めなかった孤立床は暗いまま残る。

距離場に、向きを一緒に記録する。あるマスへ初めて波が届いたとき、どの隣から来たかを書き留める。その来た方向の逆——隣へ戻る向きが、ゴールへ近づく矢印になる。波を流すループの中で歩数を書くのと同じ行で、隣の座標 − 自分の座標 を向きとして溜める。全マスにこの矢印を引くと、画面いっぱいに流れの分布が立つ。

矢印がゴール(黒い升)へ向かって渦を巻くように収束し、壁(灰色)の周りでは迂回するように向きが曲がる。床ごとに、自分の真上に来る経路が一本決まっている。

この矢印の上をキャラに歩かせる。一体の足元のマスを x / cellWy / cellH で割り出し、そのマスの矢印 flowX, flowY を速度に足す。それを毎フレーム繰り返すと、どこから出発しても矢印を辿ってゴールへ吸い込まれる。ゴールに着いた粒は別の床へ撒き直して、群れが流れ続ける。

撒いた点が矢印の筋に沿って流れ、壁を回り込みながらゴール(黒い升)へ集まる。半透明の paper を毎フレーム上から塗っているので、通り道が尾を引いて経路の束が見える。一体ごとに経路を解く処理はどこにもなく、全員が同じ flowX, flowY を読むだけで道が決まる。一点から波を流して歩数を測る BFS の距離場に、来た向きの記録を一行足すと、そのまま大群のナビゲーションになる。