逃げる相手の行く先を読む
止まっている標的なら、今いる場所へ向かえば届く。動いている標的だと、今いる場所へ向かっても着いた頃には相手はそこにいない。相手の速度を見て、少し先の未来位置を狙うと届く。未来位置を狙う pursue(追跡)。符号を逆にして未来位置から遠ざかると evade(回避)。
pursue と evade は Craig Reynolds の操舵行動(steering behaviors, 1999)の一つ。標的が今と同じ速度で lead フレーム動き続けると仮定して未来位置 p + v·lead を予測し、その一点を seek(pursue)または flee(evade)の標的に差し替える。予測の手間はベクトル一本ぶんで、相手が直進しているあいだはよく当たり、急に曲がると外れる。lead を相手との距離に比例させると、遠いほど深く読み、間合いが詰まると現在位置に寄る。
標的はゆっくり蛇行して、壁に当たると跳ね返る。二本の sin と cos を別の速さで vx, vy に重ねているので、軌跡が単純な円にならず気まぐれに曲がる。速度 vx, vy が毎フレーム手元に残るので、先読みに使える。
標的が画面をふらふらと描く。壁の手前 30 で速度の符号を反転させて、内側に留まる。
ここへ追跡者を一匹足す。狙うのは標的の今いる場所。そこへ向かう向きを maxSpeed の速度に伸ばして、今の速度との差を maxForce で頭打ちにした操舵力にして足す。曲がれる量に上限があるぶん慣性が出る。
追跡者が標的の通った跡をなぞって、いつも後ろを追う。標的が向きを変えるたびに置いていかれて、軌跡が一拍遅れる。狙っているのが標的のいた場所なので、着いた頃には標的はもうそこにいない。
先読みは、狙う一点を未来へずらす。標的の速度を lead フレームぶん延ばした位置を、新しい標的にする。
// 標的の今の位置でなく、lead フレーム先の予測位置を狙う const aimX = tg.x + tg.vx * lead const aimY = tg.y + tg.vy * lead
lead が予測の強さ。0 なら今いる場所、大きいほど遠くを読む。相手が今と同じ速度で動き続けるという仮定の上に立った一点で、seek の標的をこの aim に差し替えると pursue になる。lead を上げすぎると、標的が曲がった瞬間に外れた未来へ突っ込む。evade は符号を逆にして、未来位置から遠ざかる向きへ操舵する。
下は、先読みなし(lead=0、いた場所を狙う)と先読みあり(lead=18、行く先を狙う)の二匹を、同じ標的に同時にかける。狙っている点を薄い灰色の小さな正方形で、本体を丸で打つ。
薄い灰色の追跡者(lead=0)は後ろを追い、濃い追跡者(lead=18)は標的の進む先へ斜めに切り込んで、回り込むように間合いを詰める。同じ標的を追っているのに、狙う一点を未来へずらしただけで動き方が変わる。lead を上げると切り込みが深くなり、標的が向きを変えた直後だけ予測が外れて行き過ぎる。