I have a "pixel perfect" detection algo. It is written in allegro but the concepts should be simple to port to a direct x context.
Code:
struct BoundingBox
{
int top;
int bottom;
int left;
int right;
};
Code:
#include <algorithm>
#include "Collision.h"
bool CCollisionDetection::DetectBoundingBox(const CSprite &spriteOne, const CSprite &spriteTwo)
{
//
//Grab the bounds of the sprites
//
const BoundingBox &boundOne = spriteOne.Bounds();
const BoundingBox &boundTwo = spriteTwo.Bounds();
//if the left is greater than the right no collison
if(boundOne.left > boundTwo.right){
return false;
}//if
//if the right is less than the left no collision
if(boundOne.right < boundTwo.left){
return false;
}//if
//if the bottom is less than the top no collision
if(boundOne.bottom < boundTwo.top){
return false;
}//if
//if the top is greater than the bottom no collision
if(boundOne.top > boundTwo.bottom){
return false;
}//if
//if all the checks failed that means they are colliding
return true;
}
bool CCollisionDetection::DetectPixelPerfect(const CSprite &spriteOne, const CSprite &spriteTwo)
{
//Cannot preform collision detection on a non active sprite
if(!spriteOne.IsActive() || !spriteTwo.IsActive()){
return false;
}//if
//Preform bounding box collision to save the waste of cpu on collision that are not close
if(!DetectBoundingBox(spriteOne, spriteTwo)){
return false;
}//if
//
//Grab the sprite's bounds
//
const BoundingBox& boundOne = spriteOne.Bounds();
const BoundingBox& boundTwo = spriteTwo.Bounds();
//Grab the sprite's images
const CBitmap& imageOne = spriteOne.Image();
const CBitmap& imageTwo = spriteTwo.Image();
//
//Grab both sprite bitmask colors.
//
int spriteOneBitmask = imageOne.MaskColor();
int spriteTwoBitmask = imageTwo.MaskColor();
//
//Grab the min and max y overlap
//
int minY = std::max(boundOne.top, boundTwo.top);
int maxY = std::min(boundOne.bottom, boundTwo.bottom);
//
//Grab the min and max x overlap
//
int minX = std::max(boundOne.left, boundTwo.left);
int maxX = std::min(boundOne.right, boundTwo.right);
for(int currentY = minY; currentY < maxY; currentY++){
//
//Grab the x adjustments for grabbing the proper place in the image.
//
int spriteOneYAdjustedPixel = currentY - boundOne.top;
int spriteTwoYAdjustedPixel = currentY - boundTwo.top;
for(int currentX = minX; currentX < maxX; currentX++){
//
//Grab the position x adjustments for grabbing the proper place in the image.
//
int spriteOneXAdjustedPixel = currentX - boundOne.left;
int spriteTwoXAdjustedPixel = currentX - boundTwo.left;
//Get the current pixel for the first sprite
int spriteOneCurrentPixel = imageOne.GetPixel(spriteOneXAdjustedPixel, spriteOneYAdjustedPixel);
//Get the current pixel for the second sprite
int spriteTwoCurrentPixel = imageTwo.GetPixel(spriteTwoXAdjustedPixel, spriteTwoYAdjustedPixel);
//Special Case: If both pixel at the current position are not the mask color of the
//image then they are overlapping. Return true to the caller.
if(spriteOneCurrentPixel != spriteOneBitmask && spriteTwoCurrentPixel != spriteTwoBitmask){
return true;
}//if
}//for
}//for
return false;
}