0
\$\begingroup\$

I am making a game for android which I need hit detection between two objects. The first bitmap I have is a flying superhero, and the second bitmap is anything that he collides with.

The superhero bitmap is created on the fly by rotating the original bitmap between -90 and 90 degrees. As a result of the rotation, the bounding box is much, much larger than the non-rotated version. I have code to detect if the bounding box of the player hits any object, but visually this creates a problem when the object comes in contact with the skewed bounding box.

I need a solution that computes pixel-perfect hit detection between the player and the object, not just the bounding boxes.

I have been searching for the past 5 days for examples, tutorials, code snippets, or anything that could help me, but I haven't found a solution. The solution I'm looking for would be simply one function call similar to public boolean(obstacle theobject), where the obstacle's bitmap. coordinates, width, and height are returned with obstacle.getbitmap, obstacle.getx, obstacle.gety, obstacle.getwidth, and obstacle.getheight. The bitmap of the player is named rotatedbm and has global variables playerx, playery, playerh, and playerw.

I do not wish to implement external game engines or libraries.

I have read much on using int arrays with Bitmap.getPixels, and then comparing the arrays, but I cannot grasp the math behind comparing the arrays nor sorting out alpha values. I cannot afford to stay stuck on this one problem much long for the sake of development.

Thank you

EDIT- This is my implementation of the pseudo code. In the log, 'hit true' is never thrown but 'hit trying' is. Its not working as intended...

public boolean gethit(obstacle second){

        int px,py,ph,pw;

        Bitmap sprite1 = rotatedbm;
        Bitmap sprite2 = second.getgfx();

        px = playerx;
        py = playery;
        ph = sprite1.getHeight();
        pw = sprite1.getWidth();


        int ox = second.obx;
        int oy = second.oby;
        int oh = second.obh;
        int ow = second.obw;

        int [] AABB1bl = {px, py+ph};
        int [] AABB1tr = {px+pw, py};
        int [] AABB2bl = {ox, oy+oh};
        int [] AABB2tr = {ox+ow, oy};

        AABB2bl[0] -= AABB1bl[0];
        AABB2bl[1] -= AABB1bl[1]; 

        AABB2tr[0] -= AABB1bl[0];
        AABB2tr[1] -= AABB1bl[1];

        AABB1tr[0] -= AABB1bl[0];
        AABB1tr[1] -= AABB1bl[1];

        AABB1bl[0] -= AABB1bl[0];
        AABB1bl[1] -= AABB1bl[1];

        int start_x = AABB2bl[0];
        int start_y = AABB2tr[1];
        int end_x = AABB1tr[0];
        int end_y = AABB1bl[1];

        int ALPHAMASK = 0xFF<<24; // assuming colors are represented as 0xAARRBBGG

        int alpha1;
        int alpha2;


        Log.i("hit", "trying");
        for(int x = start_x; x < end_x; x++) 
            for(int y = start_y; y < end_y; y++) {  
              alpha1 = sprite1.getPixel(x , y*sprite1.getWidth()) & ALPHAMASK;
              alpha2 = sprite2.getPixel(x + AABB2bl[0], (y+AABB2tr[1])*sprite2.getWidth()) & ALPHAMASK;
              if(alpha1 != 0 && alpha2 != 0) {
                Log.i("hit", "true");
                return true; // you'd probably wish to return after a colliding pixel has been found
              }
            }
        return false;
}
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

1) Calculate the screen-space AABBs of the two potentially colliding objects. Note that this needs to be done after you've applied all rotations (there are very fast ways of obtaining AABBs from OBBs if you need to). You can represent AABBs in many different ways (e.g. vector2 and two floats - center and extents or two vector2s - bottom left, top right corner). I will assume the second representation - two vector2s for bottom left and top right corner.

struct AABB {
    Vector2 bottomLeft;
    Vector2 topRight;
}

2) Do a basic AABB intersection test for an early out.

3) Translate both AABBs to the coordinate space of the first one.

aabb2.bottomLeft -= aabb1.bottomLeft;  
aabb2.topRight -= aabb1.bottomLeft;  
aabb1.topRight -= aabb1.bottomLeft;  
aabb1.bottomLeft -= aabb1.bottomLeft;

4) As the AABBs are in screen-space they (should) correspond directly to the bitmap representation of your objects on-screen. You get something like:

this

Now you have to iterate through the red pixels and compare the values from the two images you have. I am assuming you would wish to compare only the alpha values so you would need to mask them out from the ints you get from getPixels(). An example in pseudo C:

int start_x = aabb2.bottomLeft.x;
int start_y = aabb2.topRight.y;
int end_x = aabb1.topRight.x;
int end_y = aabb1.bottomLeft.y;

int ALPHAMASK = 0xFF<<24; // assuming colors are represented as 0xAARRBBGG
Bitmap sprite1;
Bitmap sprite2;

for(int x = start_x; x < end_x; x++) 
for(int y = start_y; y < end_y; y++) {  
  alpha1 = sprite1.pixels[x+y*sprite1.width] & ALPHAMASK;  
  alpha2 = sprite2.pixels[(x+aabb2.bottomLeft.x)+((y+aabb2.topRight.y)*sprite2.width)] & ALPHAMASK;
  if(alpha1 != 0 && alpha 2 != 0) {
    // pixel is colliding
    return; // you'd probably wish to return after a colliding pixel has been found
  }
}
\$\endgroup\$
6
  • \$\begingroup\$ vector2 is not in the android library. i would want to just use the primitive data types before i try to do anything fancy. \$\endgroup\$
    – corey
    Jun 3, 2011 at 21:26
  • 1
    \$\begingroup\$ This is what i turned your pseudo code into. I changed your vector code into the separate x and y, but didn't do the for loop search correctly \$\endgroup\$
    – corey
    Jun 3, 2011 at 23:00
  • 1
    \$\begingroup\$ This is a great answer except that some of the code is specific to C/C++ (I think?). He's probably not using the NDK since the question is tagged Java. @corey use an int or float array with 2 indices (new int[2];) in place of vector2. \$\endgroup\$
    – Amplify91
    Jun 4, 2011 at 11:22
  • \$\begingroup\$ @Amplify91: It's still a great answer because it provides a helpful solution. Now, all the questioner needs to do, is to figure out how to get the pseudo-code adapted to Java (and there are many people who can help with that -- perhaps a separate question should be started?). \$\endgroup\$ Jun 4, 2011 at 18:36
  • 1
    \$\begingroup\$ @Randolf I agree that it's a great answer. I was just trying to be one of the people to help adapt that pseudo-code to Java :) \$\endgroup\$
    – Amplify91
    Jun 5, 2011 at 0:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .