3

对于一个项目,我们得到了一个游戏引擎来创建游戏。作为其中的一部分,我们必须在通过边界框检测方法发现可能的碰撞后实施像素级碰撞检测。我已经实现了这两个,但我的像素级测试对于小物体(在这种情况下是子弹)失败了。我已经检查过它是否适用于慢速子弹,但也失败了。

对于我的像素级实现,我使用可用的 IntBuffer(也可以使用 ByteBuffer?)为每个纹理创建位掩码。IntBuffer 是 RGBA 格式,它的大小是宽度*高度,我将它放在一个 2D 数组中,并将所有非零数字替换为 1 以创建掩码。在边界框发生碰撞后,我找到了由重叠表示的矩形(使用 .createIntersection),然后使用按位与检查该交叉点内的两个精灵的贴图是否有非零像素。

这是我的像素级测试代码:

/**
 * Pixel level test
 *
 * @param rect the rectangle representing the intersection of the bounding
 * boxes
 * @param index1 the index at which the first objects texture is stored
 * @param index the index at which the second objects texture is stored
 */
public static boolean isBitCollision(Rectangle2D rect, int index1, int index2)
{
    int height = (int) rect.getHeight();
    int width = (int) rect.getWidth();

    long mask1 = 0;
    long mask2 = 0;

    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < height; j++)
        {
            mask1 = mask1 + bitmaskArr[index1].bitmask[i][j];//add up the current column of "pixels"
            mask2 = mask2 + bitmaskArr[index2].bitmask[i][j];

            if (((mask1) & (mask2)) != 0)//bitwise and, if both are nonzero there is a collsion
            {
                return true;
            }
            mask1 = 0;
            mask2 = 0;
        }

    }


    return false;
}

我已经为此苦苦挣扎了好几天,任何帮助将不胜感激。

4

2 回答 2

2

我设法解决了我自己的问题,现在它可以正常工作了。对于任何感兴趣的人,我所做的是找到由两个精灵的两个边界框重叠创建的矩形。然后我将每个对象连同它一起放到原点,相对地,相交的矩形。应该注意的是,我将每个对象都放到了一个“单独的”原点——也就是说,之后我实际上有两个相交的矩形——每个对象一个。每个相交矩形的坐标,现在位于两个对象的位掩码 2D 数组的范围内,用于检查两个对象重叠的正确区域:

我通过位掩码从下到上从左到右循环,作为向上提供的图像数据 - 显然这是图像数据的规范。

 /**
 * My Pixel level test - 2D
 *
 * @param rect the rectangle representing the intersection of the bounding
 * boxes
 * @param index1 the index at which the first objects texture is stored
 * @param index2 the index at which the second objects texture is stored
 * @param p1 the position of object 1
 * @param p2 the position of object 2
 * @return true if there is a collision at a pixel level false if not
 */
//public static boolean isPixelCollision(Rectangle2D rect, Point2D.Float p1, Bitmask bm1, Point2D.Float p2, Bitmask bm2)
public static boolean isPixelCollision(Rectangle2D rect, Point2D.Float p1, int index1, Point2D.Float p2, int index2)
{
    int height = (int) rect.getHeight();
    int width = (int) rect.getWidth();

    byte mask1 = 0;
    byte mask2 = 0;

    //drop both objects to the origin and drop a rectangle of intersection for each along with them
    //this allows for us to have the co-ords of the rect on intersection within them at number that are inbounds.
    Point2D.Float origP1 = new Point2D.Float((float) Math.abs(rect.getX() - p1.x), (float) Math.abs(rect.getY() - p1.y));//rect for object one
    Point2D.Float origP2 = new Point2D.Float((float) Math.abs(rect.getX() - p2.x), (float) Math.abs(rect.getY() - p2.y));//rect for object two

    //to avoid casting with every iteration
    int start1y = (int) origP1.y;
    int start1x = (int) origP1.x;
    int start2y = (int) origP2.y;
    int start2x = (int) origP2.x;

    //we need to loop within the rect of intersection
    //goind bottom up and left to right
    for (int i = height - 1; i > 0; i--)
    {
        for (int j = 0; j < width; j++)
        {
            mask1 = bitmaskArr[index1].bitmask[start1y + i][start1x + j];
            mask2 = bitmaskArr[index2].bitmask[start2y + i][start2x + j];
            if ((mask1 & mask2) > 0)
            {
                return true;
            }
        }

    }
    //no collsion was found
    return false;
}
于 2012-09-09T16:33:25.807 回答
0

问题可能出在这部分代码上:

if (((mask1) & (mask2)) != 0)//bitwise and, if both are nonzero there is a collsion
{
    return true;
}

您似乎正在使用按位并检查两个值是否都非零 - 但这可能无法以这种方式工作。

例如以下表达式的值:

3 & 4 == 0

是真的

这是因为当您执行按位运算时,您需要将数字视为它们的位表示并逐位执行操作。

所以:

  3 = 0000 0011
& 4 = 0000 0100
---------------
  0 = 0000 0000

这是因为 1 位值如何相互对齐。对于位中的位并具有 1 的值 - 不同数字中同一位置的两个位需要为 1。

另一个例子是:

  3 = 0000 0011
& 2 = 0000 0010
---------------
  2 = 0000 0010

因此,在您的情况下,更好的检查是:

if ( mask1>0 && mask2>0 )//logical and if both are nonzero there is a collsion
{
    return true;
}
于 2012-09-03T23:09:59.417 回答