Pixel-perfect collision

Started by
0 comments, last by BeerNutts 12 years, 4 months ago
I've a code that creates a new mask bool for each loaded texture, however I've no idea where to go next. Logically I should return a variable, however I've no idea what and how to return.

I used this article to do it, thank you Evil Steve! I didn't want to revive a thread from 2 years ago, so I created a new one.
Advertisement
From an old project, I create a bitmask that handles this sort of thing. Wehn the sprites are load, I scan them, and when I intersect the transparent color (0 in my game), I don't set the bit, if it's a color, I do set it. Then, when checking collisions, I check the sprite's rectangle intersect, and, if they do, I then check if the object's bitmask's overlap, if so, it's a collision. i did it long ago (2001), and using old DirectX, but there's the code anyway:

The key points are in GetObjectDefintion() and SetObjectDefinition().

Good Luck!



//-----------------------------------------------------------------------------
// Set some memory aside, and copy the contents of the buffer in it
//-----------------------------------------------------------------------------
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() */


//-----------------------------------------------------------------------------
// Get the memory holding the pixel definition of the object
//-----------------------------------------------------------------------------
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() */




/**********************************************************
*
* Intersect()
*
* Check if 2 objects intersect anywhere
*
***********************************************************/
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);
}

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

This topic is closed to new replies.

Advertisement