是否通过了检查点这个问题看起来似乎很easy,我们只需要判断两点之间的距离是否小于某个阈值即可。
但是当引入转向角度属性后,且如果你的转向角度较大,你会发现你的对象永远在围绕检查点转圈。
所以会有更好的解决办法吗?
(红圆表示路径点,黑块表示玩家位置在两个路径点构成的线段上的‘投影’点)
要解决这个问题,我们至少需要两个路径点:
基础思路是使用向量投影找到在两个路径点所构成的线段上,且距离玩家最近的点。从而判断结果的值来确定玩家是否已经到达目标路径点
详细代码:
export class IsAcrossWayPoint {
/**
* 判断目标是否到达路径点
* @param source
* @param waypoints {@type 起始路径点,目标路径点}
* @returns
*/
isAcrossWayPoint(source: Core.GameObject, waypoints: [Type.Vector, Type.Vector]) {
// source对象位置到起始点的方向向量
let a = source.worldLocation.clone().subtract(waypoints[0]);
// 两个路径点之间构成的方向向量
let b = waypoints[1].clone().subtract(waypoints[0]);
// 我们假设a向量在b向量方向上的投影为a1
// 由向量投影公式可得
// a1 = (a.b / |b|^2) * b 人话就是 a1等于 (a点乘b/b的模长平方) * b
// 设 progress = a1/b;
// 推出 progress = (a.b/|b|^2)
let progress = Type.Vector.dot(a, b) / b.sqrLength;
if (progress > 1) {
return true;
} else {
return false;
}
}
}
另外一种解决办法是使用点乘来判断。前提是必须拥有目标路径点的标准方向。这种技术被赛车游戏广泛使用,赛车游戏中我们一般会提前知道玩家会从哪个方向到达检查点。所以我们只需要判断玩家距离检查点的方向向量是否和路径点的标准到达方向向量一致,就能知道玩家是否通过了检查点。
课后小测:
使用上面提到的点积的方式来校验是否通过检查点
|