这是旧的,但仍然相关,这个问题似乎没有很多答案,所以这里是:
对于整体形状不变的多边形(可能会旋转和缩放,但顶点之间的关系可能不会改变),有办法对顶点数据进行预处理,以实现对多边形中的线进行一个和/或一系列的测试如果另一个多边形与它碰撞。
我正在编写这个算法,所以我将为您提供它背后的理论,而不是现成的:
图例:&& 表示与,|| 是指或。
步骤 1a:
遍历多边形的线并针对它的所有其他点测试每条线,我们将所有其他点都在该线上或该线的“内侧”侧的线分开。
这些收集到的行在碰撞检查公式中形成一个新节点,它们被认为是相互之间的逻辑 AND 检查。
步骤 1b:
将每个孤岛顶点组分成自己的集合,并将它们分别提供给下一步:这些孤岛被视为相互之间的逻辑 AND。
步骤 1c:
如果在步骤 1a 期间收集了任何行,并且由于进入步骤 3a/3b,我们一次收集了不止一行,请重置步骤 3a/3b 中设置的所有变量,然后立即返回 1a。
步骤 2a:
穿过多边形的线并针对它的所有其他点测试每条线,我们将所有其他点都在多边形“外侧”的线分开(或者更具体地说,所有点都在非碰撞点上)线的一侧)。
这些收集的行在碰撞检查公式中形成一个新节点,它们被认为是相互之间的逻辑 OR 检查。
步骤 2b:
将每个孤岛顶点组分成自己的集合,并将它们分别提供给下一步。这些岛被视为彼此之间的逻辑 OR。
步骤 2c:
如果在步骤 2a 中收集到任何行,请重置在步骤 3a / 3b 中设置的任何变量,然后重新回到 1a。
步骤 3a:
进入这个阶段意味着没有剩下所有顶点都落在其一侧的线,这意味着我们需要更积极地收集线:
增加要在步骤 1a 和 2a 中收集的连续行数。这意味着不是所有顶点都落在一条线的一侧,而是它们必须落在至少一条收集线的一侧(1a 中的内部和 2a 中的外部)。一旦收集到任何行,这将重置回 1。
步骤 3b:
如果要收集的连续线数超过形状中的线数,则将数字重置为 2 并允许收集不连续的线(到达这里也是一个很好的迹象,表明您的网格有点复杂,您可能想要考虑将其减少一点,虽然达到 3a 没什么大不了的,因为一个简单的星形需要输入它才能解决)。
使用生成的节点进行碰撞测试时,只需将要测试的对象的形状(点/线/圆)与处理后的网格一一输入节点即可。
对于两个要进行碰撞测试的多边形,只有其中一个必须像这样处理。
创建示例多边形的公式:
1) 将示例多边形提供给步骤 1a:
图片中的红线是所有其他顶点都落入其中的所有线条,因此形状必须在所有这些线条之内,形状才能与多边形碰撞。
在 1b 之后,多边形将被分成两个(A 和 B)。
2) 将 A 和 B 送入步骤 2a:
图片中的绿线是所有其他顶点都落在其外的所有线,因此如果形状在其中一个内部,则会发生碰撞。
两个孤岛多边形 A 和 B 将在 2b 之后进一步孤岛为 C、D、E 和 F。
3) 将 C、D、E 和 F 送入步骤 1a:
多边形 C 将失去一条线(我们称其为新形状 G),D 将在步骤 1b 之后变成两条(H 和 I),并且多边形 E 和 F 没有剩余的线可以收集。
4) 将 G、H 和 I 送入步骤 2a:
在步骤 2c 之后,多边形 G 将被分成两个(J 和 K),H 将失去 2 条线(称为新形状 L),而 I 将没有剩余的线可以收集。
5) 将 J、K 和 L 送入步骤 1a:
在此之后,所有行都已通过重复 3 次步骤收集到。
原始多边形的最终公式变为: 一行上的最终公式并标记阶段 多一点视觉表示:具有视觉表示的最终公式
这是标有线条的原始多边形:Polygon with Lines Marked
使用这种方法,凹多边形测试碰撞的速度与将它们分解为凸多边形的速度相同甚至更快(最坏的情况是如果两者都具有相同数量的顶点,则最好的情况可以将测试减少到步骤 1 中的所有行和步骤 2 中的一行,如果碰撞发生在其他地方,则不再测试任何更复杂的形状曲线)。
该算法的局限性至少如下:
1) 如果多边形的顶点被动画化,则上述公式不再适用,必须重新制作。不过,这对于少量不太复杂的多边形来说不是问题,因为上述步骤并不是很复杂(需要 (n - 2)^2 的“该点位于线的哪一侧”-测试其结果可以在整个步骤中缓存和重复使用)。
2) 不自动处理多边形中的孔。孔也可以按上述方式处理,只需对其应用以下规则:与原始多边形碰撞的形状也必须 a) 与孔的线相交或 b) 不与孔多边形碰撞才能发生碰撞.
3) 我提出的如何分解多边形的规则没有针对任意复杂的多边形进行测试,可能需要进一步的规则来处理它们。
4) 你必须自己编写算法的代码,因为在我有一个可用的通用版本之前我不打算发布,这可能需要一段时间。