2012-09-03 84 views
3

對於一個項目,我們給了一個遊戲引擎來創建遊戲。作爲其一部分,我們必須在通過邊界框檢測方法發現可能的碰撞後實施像素級碰撞檢測。我已經實現了這兩個,但是我的像素級測試對於小物體(本例中爲子彈)失敗。我檢查了它是否適用於慢速子彈,但也失敗了。對於小物體,像素級碰撞檢測失敗。 (Java)

對於我的像素級實現,我使用可用的IntBuffer爲每個紋理創建位掩碼(ByteBuffer也可用?)。 IntBuffer是RGBA格式,其大小是寬*高,我把它放在一個二維數組中,並用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; 
} 

我一直在爲此而努力了幾天,任何幫助將不勝感激。

+0

從'文件:/// C:/文件%20於是%20Settings/SER /桌面/ Java3D的/鞋帶%20formula%20-%20Wikipedia,第二十條%%20free%20encyclopedia.htm'你可以找到區其中一種形狀........如果它們的併合面積小於不同形狀的面積的總和,則它們正在碰撞。這是O(n + m)比O(n * n)好得多 –

+0

感謝您的建議,但我必須實施這種測試。 – Mafro34

回答

2

我設法解決我自己的問題,現在它工作正常。對於任何感興趣的人,我所做的是找到由兩個精靈的兩個邊界框重疊而創建的矩形。然後,我將每個對象與它一起放到原點上,相對而言,就是交叉矩形。應該指出的是,我把每個對象放到一個「獨立」的起源 - 也就是說,我實際上有兩個矩形的交集 - 每個一個。每個交叉矩形的座標(現在位於兩個對象的位掩碼二維數組的範圍內)用於檢查兩個對象重疊的正確區域:

I循環底部到左上方通過位掩碼因爲提供的圖像數據很好 - 顯然這是圖像數據的常態。

/** 
* 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; 
} 
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; 
} 
+0

雖然我驚歎於我自己的愚蠢改變代碼,不幸的是不能解決問題。 我也試圖實現的轉變,因爲這有縫像它可以理清你這樣做帶來了問題: 'INT移=(INT)(p1.x -p2.x)' 則: '如果(移位<0)'' {'' MASK1 =掩碼<<( - 換檔);'' } else' ''{' = MASK2 << MASK2(移位);'' }' '((mask1&mask2)!= 0)' '''' 'return true;' '}' – Mafro34

+0

@ Mafro34位掩碼如何實現?假設我們有兩個2×2像素的子彈。在這個例子中,我認爲掩碼應該是3x3矩形。這是你如何擁有它? – norbitheeviljester

+0

如果子彈的高度是2,寬度是2,那麼這種情況下的面具也是2x2。 – Mafro34