3

In Android I use a SurfaceView to display a simple 2D game. The bitmaps (.png) with alpha (representing the game objects) are drawn on the canvas.

Now I would like to do a simple but accurate collision detection. Checking whether these bitmaps are overlapping is quite easy.

But how do I check for collisions when these bitmaps have transparent areas? My challenge is detecting whether two balls collide or not. They fill up the whole bitmap in width and height both but in all four edges, there are transparent areas of course as it's a circle in a square.

What is the easiest way to detect collisions there only if the balls really collide, not their surrounding bitmap box?

Do I have to store coordinates of as many points on the ball's outline as possible? Or can Android "ignore" the alpha-channel when checking for collisions?

caw
  • 30,999
  • 61
  • 181
  • 291

3 Answers3

13

Another method I can think of will work with simple objects that can be constructed using Paths.

Once you have two objects whose boundaries are represented by paths, you may try this:

Path path1 = new Path();
path1.addCircle(10, 10, 4, Path.Direction.CW);
Path path2 = new Path();
path2.addCircle(15, 15, 8, Path.Direction.CW);

Region region1 = new Region();
region1.setPath(path1, clip);
Region region2 = new Region();
region2.setPath(path2, clip);

if (!region1.quickReject(region2) && region1.op(region2, Region.Op.INTERSECT)) {
    // Collision!
}

Once you have your objects as Paths, you can draw them directly using drawPath(). You can also perform movement by transform()ing the path.

Dheeraj Vepakomma
  • 26,870
  • 17
  • 81
  • 104
  • 1
    Thanks, this is a really interesting and useful solution for non-circular objects! Anyway, I've not really figured out what `clip` might be ... – caw Apr 03 '12 at 00:30
  • 3
    From my understanding, the variable "clip" in the above code should be the bounding box of the path. For general purposes I use Region clip = new Region(0, 0, layoutWidth, layoutHeight); Where the layout width and height can be the size of your canvas or activity or whatever. – Steven McConnon Nov 19 '12 at 09:11
  • if any one is confuse about clip , clip represent to region e.g , RectF bounds = new RectF(); path.computeBounds(bounds, true); Region region1 = new Region(); region1.setPath(path, new Region((int) bounds.left, (int) bounds.top,(int) bounds.right, (int) bounds.bottom)); region1.setPath(path, region1); ... – Mubashir Murtaza Aug 14 '20 at 07:10
  • Note that `setPath` can return `false`, meaning that the resulting region is empty. In this case, the following check does not work for obvious reasons. – Nicolai Weitkemper Mar 02 '21 at 13:12
9

If it is ball collision you can perform analitical collision detection - it will be much faster then per-pixel detection. You only need to have two centers of balls (x1,y1) and (x2,y2) and radius r1 for the first ball and r2 for second one. Now if distance between centers of ball is less or equal of sum of radius then the balls are colliding:

    colide = sqrt((x1-x2)^2+(y1-y2)^2)<=r1+r2

but a little faster way is to compare square of this value:

   colide =  (x1-x2)^2+(y1-y2)^2<=(r1+r2)^2
theres
  • 523
  • 4
  • 13
  • 2
    Thank you very much! For the balls example, this is probably the perfect solution. I should have mentioned that I would appreciate a more general solution (e.g. per-pixel detection) but this was my fault. – caw Mar 24 '12 at 13:53
2

It's much easier to use an existing library like AndEngine instead of reinventing the wheel. I'm not sure if it can be used with a SurfaceView though. Check this article: Pixel Perfect Collision Detection for AndEngine.

Dheeraj Vepakomma
  • 26,870
  • 17
  • 81
  • 104
  • Thanks, as I don't want to use sprites, it would probably be the best approach to use parts of this code only, right? Is this the important part? https://github.com/m5/andengine-pixel-perfect/blob/master/src/com/qwerjk/andengine/collision/PixelPerfectBitMask.java And isn't there any possibility to check the color of a bitmap per pixel? I could check where there really is color (not alpha) and determine the outline of the real object this way. – caw Mar 28 '12 at 17:14