3

プロジェクトでは、ゲームを作成するためのゲーム エンジンが与えられました。その一環として、バウンディング ボックス検出方法によって衝突の可能性が見つかった後、ピクセル レベルの衝突検出を実装する必要があります。私は両方を実装しましたが、ピクセル レベルのテストは小さなオブジェクト (この場合は弾丸) では失敗します。遅い弾丸で機能するかどうかを確認しましたが、それも失敗します。

ピクセル レベルの実装では、使用可能な IntBuffer を使用して各テクスチャのビットマスクを作成します (ByteBuffer も使用できますか?)。IntBuffer は RGBA 形式で、そのサイズは width*height です。これを 2D 配列に配置し、ゼロ以外のすべての数値を 1 に置き換えてマスクを作成しました。バウンディング ボックスの衝突の後、(.createIntersection を使用して) オーバーラップによって表される四角形を見つけ、ビットごとの AND を使用して、この交差内の両方のスプライトのマップをチェックし、ゼロ以外のピクセルを探します。

ピクセルレベルテストのコードは次のとおりです。

/**
 * 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

I managed to solve my own issue and now it works properly. For anyone interested what I did was find the rectangle created by the overlap of the two bounding boxes of the two sprites. I then dropped each object to the origin along with it, relatively, the rectangle of intersection. It should be noted that I dropped each object to a "separate" origin - ie I effectively had two rectangle of intersection afterwards - one for each. The co-ordinates of each rectangle of intersection, now in bounds of the bitmask 2D arrays for both objects, were used to check the correct regions for overlap of both objects:

I loop bottom to top left to right through the bitmask as the image data provided in upside - apparently this is the norm for image data.

 /**
 * 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 になるには、同じ位置にある異なる数の 2 つのビットが 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 に答える