I recently decided to create a 2d side scroller without much thought about what kind of code I would need to write. As it turns out, very little programming can be done until 2d sprite collision is worked out, and being the perfectionist that I am, it is vital that the collision detection is pixel-perfect. I wrote the code for it, and it didn't work. I scratched my head for 2 days trying to figure out what the problem was but I couldn't find anything.
By the way, iPlayerX and iPlayerY are the coordinates of the player sprite, and it is always sprite1 for simplicity.
bool checkCollision ( int sprite1, int sprite2)
{
//get the left and right x coordinates of each sprite and the top and bottom y coordinates
int left1, left2, left3;
int right1, right2, right3;
int top1, top2, top3;
int bottom1, bottom2, bottom3;
left1 = iPlayerX;
left2 = dbSpriteX(sprite2);
right1 = iPlayerX + dbSpriteWidth(sprite1);
right2 = dbSpriteX(sprite2) + dbSpriteWidth(sprite2);
top1 = iPlayerY;
top2 = dbSpriteY(sprite2);
bottom1 = iPlayerY + dbSpriteHeight(sprite1);
bottom2 = dbSpriteY(sprite2) + dbSpriteHeight(sprite2);
//trivial rejections
if (left1 > right2 || left2 > right1 || top1 > bottom2 || top2 > bottom1)
{
return false;
}
//there's an intersection so find the coordinates of the box of intersection
if (top1 > top2) top3 = top1;
else top3 = top2;
if (bottom1 < bottom2) bottom3 = bottom1;
else bottom3 = bottom2;
if (left1 > left2) left3 = left1;
else left3 = left2;
if (right1 < right2) right3 = right1;
else right3 = right2;
//create a memblock from both sprites and find out if there's a collision
dbMakeMemblockFromImage(1, dbSpriteImage(sprite1));
dbMakeMemblockFromImage(2, dbSpriteImage(sprite2));
for (int i = left3; i <= right3; i++)
{
for (int j = top3; j <= bottom3; j++)
{
if (dbMemblockByte(1, pixelToByteNumber(i, j, iPlayerX, iPlayerY, dbSpriteWidth(sprite1))) > 0 && dbMemblockByte(2, pixelToByteNumber(i, j, dbSpriteX(2), dbSpriteY(2), dbSpriteWidth(sprite2))) > 0)
{
//collision has occurred
dbDeleteMemblock(1);
dbDeleteMemblock(2);
return true;
}
}
}
dbDeleteMemblock(1);
dbDeleteMemblock(2);
//still no collision
return false;
}
int pixelToByteNumber(int pixelX, int pixelY, int spriteX, int spriteY, int spriteWidth)
{
//first find out which pixel this is
int pixelNum = spriteWidth * (pixelY - spriteY) + (pixelX - spriteX);
//convert pixel to byte number
int byteNum = 11 + 4*pixelNum;
return byteNum;
}
Turns out my sprites weren't entirely transparent. I don't know how I figured that out because I made the images in Photoshop with total transparency and saved them as PNGs, but whatever. I tried the collision again using images that I was sure had total transparency and it worked perfectly! I also changed the collision check to return true if the value of the alpha is greater than 30 to clear up any fuzzy edges.
However, I honestly have no idea how to make the collision work with my original sprite as it seems to have a sort of half-transparent border around it that doesn't even show up in Photoshop. This isn't really so much of a question I guess, but I did want to share my code with other developers having similar problems, and also ask for any insight you guys have on how I can possibly improve my code. Thanks for any help!