如何将像素完美碰撞应用于旋转精灵?

How to apply pixel perfect collision to rotated sprites?

我不知道如何处理或解决这个问题。我看过一些教程,但它们适用于已经知道自己在做什么的程序员。我看了一个关于如何执行适用于常规边界框的像素碰撞形式的视频,如果边界框发生碰撞,它会检查两个相交框中的任何非透明像素是否重叠。如果他们这样做,那么布尔值将 return 为真值。我在哪里以及如何开始在旋转对象中改变边界框的轴以补充纹理的外观?我不希望被指向外部教程,因为我读过的大多数教程都假定程序员知道作者正在谈论的一切。

我还查看了一些源代码,它们完美地展示了我正在寻找的内容,但似乎我需要非常深入的解释才能对阅读代码有所帮助。

首先,我真的不建议这样做,因为它要么是计算密集型的,要么是资源密集型的(或两者兼而有之)。

就是说,一个想法是仍然使用您前面提到的 AABB 像素对像素的直接方法。这需要您在内存中维护您自己的 像素数据以仅用于碰撞,而不是严格依赖纹理数据。

更具体地说,使用此方法您必须生成本质上是 "image" 或某种二维矩阵的内容,即 represents/follows 旋转图像的像素。但是您不会像处理普通图像那样在其中存储颜色信息。相反,结构中的每个 "pixel" 或条目都应是碰撞数据:"block" 或 "not block"。您可以轻松地使用 bitmask 来表示这一点,1 表示 "block",0 表示 "not block",并且每个像素需要一位。 (注意:通常你不需要的不仅仅是一个布尔值 "on" & "off" 为此,但你可能需要每个像素的不同类型的碰撞;如果是这样,位掩码将不起作用,而是对每个像素需要的任何内容进行编码,无论总体思路保持不变)

为精灵生成位掩码(或其他此类结构)将使您能够仅使用 AABB 方法;您所要做的就是使用生成的位掩码而不是直接使用纹理数据,其他一切都和以前一样。但是我们如何生成它呢?这就是这种方法的真正难点,因为当您告诉它进行旋转时,您生成自己的图像基本上是在复制图形卡的工作。

您基本上会 "draw" 自己制作旋转图像。这可以通过逐个像素地遍历基础纹理图像数据,并对每个像素应用旋转 transformation matrix 以使其到达 bitmask/buffer 中的正确目的地来完成。一旦你有了正确的目的地,你就会测试 "block" 或 "not block" 的图像数据(使用你提到的透明度)并相应地在那里写一个 1 或 0。

在生成时,您还应该跟踪局部最小值和最大值;也就是说,旋转后的图像向左、向右、向上和向下移动多远,只是为了给它一个真正的 AABB 以供快速检查(即 "Do I even need to check per-pixel collision?")

为了完全准确,您可能需要知道您正在使用哪种 interpolation/rounding 算法(双线性、最近邻等),这可能会变得很丑陋。图形系统通常会做非常复杂的事情,所以仅仅为了碰撞就考虑所有这些是非常极端的。归根结底,即使应用此方法,它也可能不会真正 "pixel perfect" 达到 "perfectly synchronized with the rendered image output",除非你真的在 完全 复制什么XNA / DirectX 正在做。

最后,这一代是什么时候发生的?答案是每次旋转!否则,您将检查过时的数据。显然,您可以只为每个精灵保留一个缓冲区并不断更改它,以免占用太多内存。但这确实意味着可能 每帧一次 如果你一直在旋转。如果多个精灵都旋转很多,这意味着每帧多次。可能不是最适合计算的。