See the Pen 流れに沿おうとするビークル by kana (@kanaparty) on CodePen.
ビークル(流れている点)は毎フレームごとに、今進んでいる進路上の点が道幅からでてしまうようであれば、
その進路上の点から道の真ん中と垂直に交わる点のちょっと先を目標に動くようにしています。
↓この部分
//目標の方向を決める updateSeek(){ //進行方向 this.predict = Vector.copy(this.velocity); //進行方向の50px先を予測ポイントとする this.predict.normalize().mult(50); this.predict.add(this.vlocation); //進行方向と、ラインの法線の接点を求める this.normalPoint = this.getNormalPoint(this.predict, path); var distance = Vector.sub(this.predict, this.normalPoint); //距離がラインの幅の半分よりはみ出ていたら、目標をライン上の点にする if(distance.mag() > path.radius){ //法線の接点より50ピクセル先を目標とする var target = Vector.copy(path.v); target.normalize().mult(50); target.add(this.normalPoint); var dir = Vector.sub(target, this.vlocation); dir.limit(5); //操舵力 = 目標への速度 - 現在の速度 var steer = Vector.sub(dir, this.velocity); steer.normalize().limit(0.2); this.acceleration.add(steer); } }
この中の、getNormalPoint(this.predict, path)というところで進路上の点から道の真ん中と垂直に交わる点を求めています。
中身は抜き出して書くとこんな感じ↓
/** * 進路上の点から道の真ん中と垂直に交わる点を求める * @param point 進路上の点 * @param pathStart 道のスタートの点 * @param pathEnd 道の終わりの点 */ function getNormalPoint(point, pathStart, pathEnd){ var ap = Vector.sub(point, pathStart);//進行方向の点から道のスタート地点のベクトル var ab = Vector.sub(pathEnd, pathStart);//道の方向ベクトル //道のスタート地点から法線と道の交点までの距離でスケーリング ab.normalize().mult(Vector.dot(ap,ab)); //位置をスタート地点からスケーリングした分移動 var normalPoint = Vector.copy(pathStart).add(ab); return normalPoint; }
apとabの内積が道のスタート地点から法線と道の交点までの距離(だと理解しているけれどあってるんでしょうか)
3つの点から垂直に交わる点を出すのはまた使うときがありそうなのでメモしておきます。
See the Pen 3つの点から垂直に交わる交点を求める by kana (@kanaparty) on CodePen.