For a project we were given a game engine off which to create a game. We, as part of this, have to implement pixel level collision detection after a possible collision has been found via a bounding box detection method. I have implemented both but my pixel level test fails for small objects (bullets in this case). I have checked if it works for slow bullets but that fails too.
For my pixel level implementation I create bitmasks for each texture using an the available IntBuffer (a ByteBuffer is available too?). The IntBuffer is in RGBA format and its size is width*height, I placed this in a 2D array and replaced all non-zero numbers with 1's to create the mask. After a collision of bounding boxes I find the rectangle represented by the overlap (using .createIntersection) and then check the maps of both sprites within this intersection for a nonzero pixel from both using bitwise AND.
Here is my code for the pixel level test:
/**
* 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;
}
I've been struggling with this for days and any help will be greatly appreciated.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With