Jump to content
  • Advertisement
Sign in to follow this  
DominicHughes

Having Troubles with my Per Pixel Collision Function :(

This topic is 2524 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello I'm working on a function that does per pixel collision and I have the idea of having 2 surfaces as parameters for this function.

Then basically create integer variables for each side of the 2 surfaces.

And then cleanly analyse them if the first surface of one of the 4 sides is by pixel in collision with the second surface by one of the second surface 4 sides then do something.

The problem is I don't know how to analyse each side aka *integer variables* for pixel collisions for the first and second surface any tips or solutions would be helpful.


Here is my Code Below


bool PerPixelCollision(SDL_Surface *image,SDL_Surface *Intersection_area)
{
int left_image, left_intersection_area;
int right_image, right_intersection_area;
int top_image, top_intersection_area;
int botttom_image, bottom_intersection_area;


}

Share this post


Link to post
Share on other sites
Advertisement
well, you could AND two bit-wise masks together and if you get any true's that would be a collision detect. Perhaps there is a more efficient way to do that via the alpha channels, but i cant say for sure.

Share this post


Link to post
Share on other sites
I did per-pixel collision in a game long ago (2000/2001) using C and DirectX. I'll post the code below, but, I don't feel like explaining everything.

The basic idea is, when I load an image, I scan it, recording if the color is transparent or not (I used 0 as transparent). I would then store every pixel in a bit-map array; if it's a color, it was 1, if it was transparent, I used 0. I stored this in a hash-table list, with the address of the image as the key

During collision check, I 1st check if the rectangle intersect, if they do, I then find the overlapping rectangles, and then check each bit if, and if any of them are both 1's (AND'ing), then they collide.

Good Luck!

Code when loading image. pucBuffer is a IDirectDrawSurface7, but I get the raw bitmap stored in puwPointer (16-bit colors). pulCopyPointer is the bit-mask'd bitmap array.


void SetObjectDefinition(UCHAR *pucBuffer)
{
UWORD *puwPointer;
IDirectDrawSurface7 *pdds1;
DDSURFACEDESC2 ddsd1;
ULONG *pulCopyPointer;
ULONG ulX, ulY;
tStringHash Hash;
ULONG ulCount = 0;

// cast
pdds1 = (IDirectDrawSurface7 *)pucBuffer;

// setup surface descriptions
ZeroMemory(&ddsd1, sizeof(ddsd1));
ddsd1.dwSize = sizeof(ddsd1);
ddsd1.dwFlags = DDSD_PITCH | DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_LPSURFACE;

// now get the surface
pdds1->Lock(NULL, &ddsd1, DDLOCK_WAIT | DDLOCK_READONLY, NULL);

puwPointer = (UWORD *)ddsd1.lpSurface;

/* allocate the memory, zero, and copy it into it */
pulCopyPointer = (ULONG *)malloc(((ddsd1.dwHeight * ddsd1.dwWidth)/8) + 4);
memset((void *)pulCopyPointer, 0, ((ddsd1.dwHeight * ddsd1.dwWidth)/8) + 4);

for (ulY = 0; ulY < ddsd1.dwHeight; ulY++)
{
for (ulX = 0; ulX < ddsd1.dwWidth; ulX++)
{
// If it's not zero, set bit
if(*(puwPointer + ulX + (ulY * ddsd1.lPitch/2)))
{
SET(*(pulCopyPointer + (ulCount/32)), (ulCount%32));
}
ulCount++;
}
}

// unlock
pdds1->Unlock(NULL);

/* now put in hash table, and then in a list */
Hash.cName = (CHAR *)pucBuffer;
Hash.ulNumber = (ULONG)pulCopyPointer;

// now make list
pPixelList = AddToList(pPixelList, CreateNode((void *)&Hash, sizeof(Hash)));

} /* endof SetObjectDefinition() */


Code for getting the bitmask'd bitmap (what I called an Object Definition)

ULONG *GetObjectDefinition(UCHAR *pucBuffer)
{
ULONG ulIndex;
tStringHash *pHash;

// loop list looking for this buffer
LOOP_LIST(ulIndex, pHash, tStringHash, pPixelList)
{
if (pHash->cName == (CHAR *)pucBuffer)
{
// found it
return ((ULONG *)pHash->ulNumber);
}
}

// Not suppose to be here!
LOG_ERROR("GetObjectDefinition: Bad buffer!\n"));
FLUSH;

return (NULL);

} /* endof GetObjectDefinition() */


And, here's the collision check code:

BOOL Intersect(tScreenObject *pScreenObj1, tScreenObject *pScreenObj2)
{
BOOL bReturn = FALSE;
tSizeAndLoc Obj1, Obj2, RectObj1, RectObj2;
LONG lTempX, lTempY;
ULONG *pulPointer1, *pulPointer2;
ULONG ulCount1, ulCount2;

// 07/29/01 (Friday, damnit, what am I doing? Well, not drinking obviously!)
// Update to decide square or circle bounding box

// 09/20/01 Updated to check the actual bitmaps (You knew you'd have to damnit!)

Obj1 = pScreenObj1->SizeAndLoc;
Obj2 = pScreenObj2->SizeAndLoc;

// Check rectangles 1st
// Whew!
if ((Obj1.lLocX + (LONG)Obj1.ulSizeX >= Obj2.lLocX) && (Obj1.lLocX <= Obj2.lLocX + (LONG)Obj2.ulSizeX))
if ((Obj1.lLocY + (LONG)Obj1.ulSizeY >= Obj2.lLocY) && (Obj1.lLocY <= Obj2.lLocY + (LONG)Obj2.ulSizeY))
{
// 1st, check if it's a bomb (ugly, I know!)
if ((((tBullet *)pScreenObj1)->ulType == BOMB) ||
(((tBullet *)pScreenObj2)->ulType == BOMB))
{
// just return!
return (TRUE);
}

// OK, rectangles intersect, so check bitmaps

// find rectangles we should check for each object
// check each side versus other side
if (Obj1.lLocX > Obj2.lLocX)
{
RectObj1.lLocX = 0;
RectObj2.lLocX = Obj1.lLocX - Obj2.lLocX;
}
else
{
RectObj2.lLocX = 0;
RectObj1.lLocX = Obj2.lLocX - Obj1.lLocX;
}
if (GET_RIGHT(Obj1) > GET_RIGHT(Obj2))
{
RectObj1.ulSizeX = GET_RIGHT(Obj2) - MAX(Obj1.lLocX, Obj2.lLocX);
RectObj2.ulSizeX = RectObj1.ulSizeX;
}
else
{
RectObj2.ulSizeX = GET_RIGHT(Obj1) - MAX(Obj1.lLocX, Obj2.lLocX);
RectObj1.ulSizeX = RectObj2.ulSizeX;
}
if (Obj1.lLocY > Obj2.lLocY)
{
RectObj1.lLocY = 0;
RectObj2.lLocY = Obj1.lLocY - Obj2.lLocY;
}
else
{
RectObj2.lLocY = 0;
RectObj1.lLocY = Obj2.lLocY - Obj1.lLocY;
}
if (GET_BOTTOM(Obj1) > GET_BOTTOM(Obj2))
{
RectObj1.ulSizeY = GET_BOTTOM(Obj2) - MAX(Obj1.lLocY, Obj2.lLocY);
RectObj2.ulSizeY = RectObj1.ulSizeY;
}
else
{
RectObj2.ulSizeY = GET_BOTTOM(Obj1) - MAX(Obj1.lLocY, Obj2.lLocY);
RectObj1.ulSizeY = RectObj2.ulSizeY;
}

pulPointer1 = GetObjectDefinition(pScreenObj1->pucBuffer);
pulPointer2 = GetObjectDefinition(pScreenObj2->pucBuffer);


// now loop through one of em, checking the color
for (lTempY = 0; lTempY < (LONG)RectObj1.ulSizeY; lTempY++)
{
// increase count to next line
ulCount1 = (Obj1.ulSizeX * (RectObj1.lLocY + lTempY)) + RectObj1.lLocX;
ulCount2 = (Obj2.ulSizeX * (RectObj2.lLocY + lTempY)) + RectObj2.lLocX;

for (lTempX = 0; lTempX < (LONG)RectObj1.ulSizeX; lTempX++)
{
// check for not 0
if (IS_SET(*(pulPointer1 + (ulCount1/32)), (ulCount1%32)) &&
IS_SET(*(pulPointer2 + (ulCount2/32)), (ulCount2%32)))
{
bReturn = TRUE;
break;
}
ulCount1++;
ulCount2++;
}

if (bReturn)
{
break;
}
}
}

return (bReturn);
}


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!