• Announcements

Archived

This topic is now archived and is closed to further replies.

pixel perfect collision problem

Recommended Posts

Hey, I''ve been driving myself insane lately to try and get a Pixel Perfect collision detection routine to work for my 2d game using DirectDraw7. I''ve read all the tutorials here, I''ve searched this forum and read as many posts as I could find about PP, and I feel like I am SO close. So let me just say first off, I understand the theory 100% behind it, I am just having trouble getting it to work. Here''s my whole collision function(sorry for the long post) player1 and player2 are members of my own sprite class, containing an array of members "frame" which is a DirectDraw7 surface, representing each different bitmap I load in.

//returns 1 for a collision, 0 for no collision
int Collision()
{
int AX1 = player1.x;
int AY1 = player1.y;
int BX1 = player2.x;
int BY1 = player2.y;

int AX2 = AX1 + player1.width;
int AY2 = AY1 + player1.height;
int BX2 = BX1 + player2.width;
int BY2 = BY1 + player2.height;
int CX1, CY1, CX2, CY2;	//to hold collision rect
int aStartX, bStartX, aStartY, bStartY, aEndX, bEndX, aEndY, bEndY;
int q, r;

//if any of these four cases are TRUE, no collision can have occured
if(BY2 < AY1) return(0);
if(AY2 < BY1) return(0);
if(BX2 < AX1) return(0);
if(AX2 < BX1) return(0);

//collision MIGHT have occured
if(AX1 < BX1)
{
//set the overlapping coords
CX1 = BX1;
CX2 = AX2;

aStartX = CX1 - AX1;
bStartX = 0;
aEndX	= 128;
bEndX	= CX2 - CX1;
}
else
{
CX1 = AX1;
CX2 = BX2;

bStartX = CX1 - BX1;
aStartX = 0;
bEndX	= 128;
aEndX	= CX2 - CX1;
}

if(AY1 < BY1)
{
CY1 = BY1;
CY2 = AY2;

aStartY = CY1 - AY1;
bStartY = 0;
aEndY	= 128;
bEndY	= CY2 - CY1;
}
else
{
CY1 = AY1;
CY2 = BY2;

bStartY = CY1 - BY1;
aStartY = 0;
bEndY	= 128;
aEndY	= CY2 - CY1;
}

DDSURFACEDESC2 ddsd1, ddsd2;

//Clear out the ddsd struct
memset(&ddsd1, 0, sizeof(ddsd1));
ddsd1.dwSize = sizeof(ddsd1);

memset(&ddsd2, 0, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);

//lock the buffers
player1.frame[player1.curr_frame]->Lock(NULL, &ddsd1, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
player2.frame[player2.curr_frame]->Lock(NULL, &ddsd2, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);

UCHAR *pixel1 = (UCHAR *)ddsd1.lpSurface;
int pitch1 = ddsd1.lPitch;

UCHAR *pixel2 = (UCHAR *)ddsd2.lpSurface;
int pitch2 = ddsd2.lPitch;

q = bStartX;
r = bStartY;
for(int i=aStartY; iUnlock(NULL);
player2.frame[player2.curr_frame]->Unlock(NULL);

return 1;
}
q++;
}
r++;
}

player1.frame[player1.curr_frame]->Unlock(NULL);
player2.frame[player2.curr_frame]->Unlock(NULL);

return 0;
}
[code]
I hope this makes any sense...
I *believe* my problem is in here:
[code]
q = bStartX;
r = bStartY;
for(int i=aStartY; iUnlock(NULL);
player2.frame[player2.curr_frame]->Unlock(NULL);

return 1;
}
q++;
}
r++;
}

this is where I''m testing each pixel to see if it is NOT my transparent color(219 - i''m using 8bit mode, 219 is the palette index) The function ALWAYS returns before any non-transparent pixels are on top of each other. My brain is fried right now, so if you need more info on my function, please ask. and if anyone can see any stupid mistakes I''m making(as I''m sure I''m making at least one) please help me out. thanks in advance...

Share on other sites
Do you really NEED pixel perfect collision detection ??

Pixel perfect collision detection involving Lock() & UnLock() does not strike me as fast...

But of course if you have enough cycles to spare....

Share on other sites
I''ve done PP collision detection with Directx8 and here is what I think is the best way to go about it. First at initialization time, you should pre-process a set of binary collision masks from all your textures/surfaces that are going to be involved in PP collision tests. Doing this means there is no locking and unlocking during run-time of textures/surfaces. The rest should then be obvious. First test for bounding rect collision, if a collision has occured you need to compute the dimensions of the overlapped rect involved in collision. Then using this overlapped rect, you need to compute offsets into each collision mask that represents the current texture/surface being displayed for the two colliding entities. You then perform the overlap test. The whole process is quite involved so be prepared to sit down with a pen a paper and hammer it for a while, but it looks like you''ve already figured the hard part.

Share on other sites
See my code at http://www.gamedev.net/community/forums/topic.asp?topic_id=69411 this also includes an explination of the code. The code is kinda old because I moved to DirectX8 for graphics, but it should be all you need. It isn''t coded to work with a surface that is drawn flipped, but that''s not too hard to do.

Share on other sites
DeathCheese,

I''ve done exactly what you did not too long ago, and went through probably the same progressions. I first tried locking both overlapping surfaces every time they intersected, but that was painfully slow. Then I did what level10boy suggested, and everytime I loaded a new frame, I associated a bitmask with it at load-time, and I now have pixel-perfect collision.

If you want, I''d be glad to share that part of the code with you. It''s done in DX7, and it supports page flipping.

Nutts

Share on other sites

Yea, that''s what I did as well.
Really speeds things up.
I use it for animated and non-animated sprites.

I read John Amato''s article in the Articles and Resources section, and re-adapted the algos with bitmasks. I was really happy with the result.

Guy

• Forum Statistics

• Total Topics
628290
• Total Posts
2981858

• 11
• 10
• 10
• 11
• 17