这是我在解决这个问题时的想法。可能有更简单的答案,但我没有找到。
1.判断一个点是否有效。
为此,我实际上有每个障碍物的 CGPath 表示。我从PhysicsEditor 导出路径,然后通过将它们转换为CGPath 的自定义脚本加载它们。我总是将该 CGPath 与我从路径创建的 GKObstacle 一起存储。最后,我可以调用CGPathContainsPoint 来确定障碍物包含的点。如果为真,我知道该观点无效。
2。一旦点无效,找出点击了哪个障碍物。
通过我在 #1 中的方法,我已经掌握了 CGPath 和它所属的障碍。
3.查找最近的顶点
现在我知道了障碍物,找到离正在移动的单位最近的顶点。我找不到点击点的壁橱顶点,因为那可能在拐角处。相反,找出所需位置和单位之间的向量。然后,从所需位置通过顶点绘制一条不可见的线。我用这个方程来找出线会交叉的地方。
// http://stackoverflow.com/questions/1811549/perpendicular-on-a-line-from-a-given-point
let k = ((end.y - start.y) * (hitPoint.x - start.x) - (end.x - start.x) * (hitPoint.y - start.y)) / ((end.y - start.y) * (end.y - start.y) + (end.x - start.x) * (end.x - start.x))
let x4 = hitPoint.x - k * (end.y - start.y)
let y4 = hitPoint.y + k * (end.x - start.x)
let ret = float2(x: x4, y: y4)
4.按单元大小向移动单元偏移交点
知道路径与朝向单元的向量相交的位置,我们可以移动到交叉点 +(向量 * 单元大小)。
5.边缘案例
当您有两个相互接触的障碍物,或者如果您有非常大的障碍物时,这会变得很棘手。用户可能认为他们正在移动到地图的远端,但此脚本将返回到可能在附近的壁橱有效点。正因为如此,我废弃了所有的代码,我只是不允许你移动到无效的位置。出现红色 X 和蜂鸣声,提示用户在地图上选择一个新的有效位置。
6.演示机器人
我可能是错的,但我隐约记得 Apple 的 DemoBots 有类似的逻辑——它们也可能是一个很好的参考。
7.调试层
我花了很长时间才得到一个概念证明。我强烈建议在调试层上画线来验证你的逻辑。