Collision Detection: John Amato Pixelsplash Software
Collision Detection: John Amato Pixelsplash Software
Collision Detection: John Amato Pixelsplash Software
file:///C:/Documents%20and%20Settings/Owner/My%20Documents/l...
Collision Detection
GameDev.net
Collision Detection
left1, left2;
right1, right2;
top1, top2;
bottom1, bottom2;
left1 = object1->x;
left2 = object2->x;
right1 = object1->x + object1->width;
right2 = object2->x + object2->width;
top1 = object1->y;
top2 = object2->y;
bottom1 = object1->y + object1->height;
bottom2 = object2->y + object2->height;
if (bottom1 < top2) return(0);
if (top1 > bottom2) return(0);
if (right1 < left2) return(0);
if (left1 > right2) return(0);
return(1);
};
Going this route usually works fairly well, but it has a major flaw in that for most normal images, it
will tend to "overdetect" collision. The problem here is obvious, and Figure 1 shows a classic
example. Figure 1 shows two perfect circles - balls let's say - which we want to detect collision on.
Because of the roundish shape of the images, the corners of each bitmap contain empty space. But
the bounding rectangles of each image are clearly intersecting, so a traditional collision detecting
algorithm (like the one listed above) would flag this as a hit.
Figure 1:
____________
|
**
|
| ******** |
|**********|
|**********|
| ********_|________
|
** | | **
|
-----------******** |
|**********|
|**********|
| ******** |
|
**
|
-----------This annoys gamers a great deal, and so some game designers decide to define a somewhat smaller
http://www.pdf4free.com
22/1/2007 20:28
file:///C:/Documents%20and%20Settings/Owner/My%20Documents/l...
rectangle than the full extents of the image, and use this smaller rectangle for the collision
detection. A good figure to use is 80 percent of the full bounding box of the image. First, we add
four new fields to the sprite data type, called col_width, col_height, col_x_offset, and col_y_offset.
During initialization, wherever we are defining our sprite widths and heights, we will also calculate
the col_widths and col_heights to be 20% smaller. Then we will define the offset fields to describe
where to set the bounding box relative to the object's coordinates. This will look something like this:
object->width = <ACTUAL BITMAP WIDTH>;
object->height = <ACTUAL BITMAP HEIGHT>;
object->col_width = object->width * 0.80;
object->col_height = object->height * 0.80;
object->col_x_offset = (object->width - object->col_width) / 2;
object->col_y_offset = (object->height - object->col_height) / 2;
Then, we can rewrite the above Sprite_Collide() to the following:
// Object-to-object, reduced bounding-box collision detector:
short int Sprite_Collide(sprite_ptr object1, sprite_ptr object2) {
int
int
int
int
left1, left2;
right1, right2;
top1, top2;
bottom1, bottom2;
http://www.pdf4free.com
22/1/2007 20:28
file:///C:/Documents%20and%20Settings/Owner/My%20Documents/l...
http://www.pdf4free.com
22/1/2007 20:28
file:///C:/Documents%20and%20Settings/Owner/My%20Documents/l...
As you might imagine, this is rather lengthy, and takes a lot more execution time. The code for this
type of collision detection is as follows:
// Full object-to-object pixel-level collision detector:
short int Sprite_Collide(sprite_ptr object1, sprite_ptr object2) {
int left1, left2, over_left;
int right1, right2, over_right;
int top1, top2, over_top;
int bottom1, bottom2, over_bottom;
int over_width, over_height;
int i, j;
unsigned char *pixel1, *pixel2;
left1 = object1->x;
left2 = object2->x;
right1 = object1->x + object1->width;
right2 = object2->x + object2->width;
top1 = object1->y;
top2 = object2->y;
bottom1 = object1->y + object1->height;
bottom2 = object2->y + object2->height;
// Trivial rejections:
if (bottom1 < top2) return(0);
if (top1 > bottom2) return(0);
if (right1 < left2) return(0);
if (left1 > right2) return(0);
// Ok, compute the rectangle of overlap:
if (bottom1 > bottom2) over_bottom = bottom2;
else over_bottom = bottom1;
if (top1 < top2) over_top = top2;
else over_top = top1;
if (right1 > right2) over_right = right2;
else over_right = right1;
if (left1 < left2) over_left = left2;
else over_left = left1;
// Now compute starting offsets into both objects' bitmaps:
i = ((over_top - object1\1->y) * object1->width) + over_left;
pixel1 = object1->frames[object1->curr_frame] + i;
j = ((over_top - object2->y) * object2->width) + over_left;
pixel2 = object2->frames[object2->curr_frame] + j;
// Now start scanning the whole rectangle of overlap,
// checking the corresponding pixel of each object's
// bitmap to see if they're both non-zero:
for (i=0; i < over_height; I++) {
for (j=0; j < over_width; j++) {
if (*pixel1 > 0) && (*pixel2 > 0) return(1);
pixel1++;
pixel2++;
}
pixel1 += (object1->width - over_width);
pixel2 += (object2->width - over_width);
http://www.pdf4free.com
22/1/2007 20:28
file:///C:/Documents%20and%20Settings/Owner/My%20Documents/l...
}
// Worst case! We scanned through the whole darn rectangle of overlap
// and couldn't find a single colliding pixel!
return(0);
};
Because it runs so long, this type of collision detection should probably be minimized in your game
implementations. You may want to determine at run-time which objects need full, object-to-object
pixel-level collision detection and which objects can get away with one of the cheaper varieties. The
best way to determine this is usually by good old-fashioned experimentation.
This last algorithm can be sped up substantially by a number of methods including loop-flipping,
non-indexed loops, and possibly loop unrolling. Also, the increment for pixel1 and pixel2 at the
bottom of the outer loop can be precomputed.
Well, that's it for this time. Next maybe we'll talk a little about 3D collision detection.
JBA
Discuss this article in the forums
Date this article was posted to GameDev.net: 9/15/1999
(Note that this date does not necessarily correspond to the date the article was written)
See Also:
Collision Detection
1999-2007 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
Comments? Questions? Feedback? Click here!
http://www.pdf4free.com
22/1/2007 20:28