So it took me several days to figure this out simply because there doesn't seem to be any real accurate guides for this out there. I did finally find an extremely helpful tutorial Here and worked off this.
Why go through all this trouble for pixel perfect collision detection? Simple, if you're making games with dynamic objects or really any object that doesn't have simplistic shape, it's very hard to work with basic collisions as you'd be using the borders of the image itself (the transparent borders usually) instead of the actual pixels in the image. With my method, collision will only be triggered upon pixels touching, and not simply on transparent borders touching.
First, the Code: *TIP* If you want to know where all the logic behind detecting whether or not collision is possible, see the previously referenced tutorial HERE
// returns a HashSet of strings that list all the pixels in an image that aren't transparent
// the pixels contained in the HashSet follow the guideline of:
// x,y where x is the absolute x position of the pixel and y is the absolute y position of the pixel
public HashSet<String> getMask(GameObject go){
HashSet<String> mask = new HashSet<String>();
BufferedImage image = null;
try {
image = ImageIO.read(new File (go.getDefaultImageLocation()));
} catch (IOException e) {
System.out.println("error");
}
int pixel, a;
for(int i = 0; i < image.getWidth(); i++){ // for every (x,y) component in the given box,
for( int j = 0; j < image.getHeight(); j++){
pixel = image.getRGB(i, j); // get the RGB value of the pixel
a= (pixel >> 24) & 0xff;
if(a != 0){ // if the alpha is not 0, it must be something other than transparent
mask.add((go.xPos+i)+","+(go.yPos- j)); // add the absolute x and absolute y coordinates to our set
}
}
}
return mask; //return our set
}
// Returns true if there is a collision between object a and object b
public boolean checkCollision(GameObject a, GameObject b){
// This method detects to see if the images overlap at all. If they do, collision is possible
int ax1 = a.getxPos();
int ay1 = a.getyPos();
int ax2 = ax1 + a.getWidth();
int ay2 = ay1 + a.getHeight();
int bx1 = b.getxPos();
int by1 = b.getyPos();
int bx2 = bx1 + b.getWidth();
int by2 = by1 + b.getHeight();
if(by2 < ay1 || ay2 < by1 || bx2 < ax1 || ax2 < bx1)
{
return false; // Collision is impossible.
}
else // Collision is possible.
{
// get the masks for both images
HashSet<String> maskPlayer1 = getMask(player1);
HashSet<String> maskPlayer2 = getMask(player2);
maskPlayer1.retainAll(maskPlayer2); // Check to see if any pixels in maskPlayer2 are the same as those in maskPlayer1
if(maskPlayer1.size() > 0){ // if so, than there exists at least one pixel that is the same in both images, thus
System.out.println("Collision" + count);// collision has occurred.
count++;
return true;
}
}
return false;
}
Pseudo code for how this works:
- Anytime 2 images overlap, there is a possibility of collision and collision detection is triggered
- A mask is created for each image, the mask simply logs the coordinates of all non-transparent pixels
- The two masks are compared
- if the two masks share any similar values than collision is triggered
Notes on my code:
GameObject simply refers to the class I set up to control all game objects. Some methods I call during this code include .getWidth(), .getHeight(), and .getDefaultImageLocation(). Both .getWidth() and .getHeight() simply return the width/height of the Image used for the GameObject. In order to set up a BufferImage I needed an image location so I set up a .getDefaultImageLocation() method which simply returns a string value of the default image location (such as "images/player1/player1Default.png").
As I was so excited to finally have this working, I didn't take a whole lot of time to clean up the code or fully test it. If you see any room for improvement or any potential errors, PLEASE LET ME KNOW!
All feedback is appreciated, and I hope I've helped someone out there who, like me, wasn't satisfied with simple (if box1 is touching box2) { collision;}.


Sign In
Create Account

Back to top









