pixel collision detection help

Started by
3 comments, last by apollyon 21 years, 10 months ago
I think I did this right, but I'm not sure... it's reporting a collision at the first time it runs through the loop. OK I AM PUTTING COMMENTS IN FOR MR. I'M TOO GOOD FOR MYSELF. (pardon my debug/test/console stuff)
          
int CWaterPolo::CheckCollision ( CPlayer *Player, CObject *Object )
{
// DDSURFACEDESC TO GET PITCH WHEN I LOCK SURFACE

	DDSURFACEDESC2 ddsdBlank;
	DDRAW_INIT_STRUCT(ddsdBlank);
// RECTS FOR BOUNDING BXES

	RECT rOne, rTwo, rOverlap;
	RECT rOneOverlap, rTwoOverlap;
// WIDHT AND HEIGHT OF OVERLAP

	int overlapWidth, overlapHeight;
// LOOP VARS

	int i, j;
// PIXELS FOR SURFACES

	UINT *pixel1, *pixel2;
// USING THIS TO CHEAT OUT OF THE LOOP

bool iscollision = false;
// WIDTH OF BITMAPS

	int oneWidth, twoWidth;
// USED FOR MAKING THE CODE A LITTLE EASIER TO READ

// X AND Y POSITIONS

	int onex;
	int oney;
	int twox;
	int twoy;
// THE COLOR KEY

	UINT ColorKey = _RGB16BIT565(255, 0, 255);

// FILL IN COMPARISON RECTS

	rOne.left = Player->GetX();
	rTwo.left = Object->GetX();
	rOne.right = Player->GetX() + Player->CurrBitmap->GetWidth();
	rTwo.right = Object->GetX() + Object->GetWidth();
	rOne.top = Player->GetY();
	rTwo.top = Object->GetY();
	rOne.bottom = Player->GetY() + Player->CurrBitmap->GetHeight();
	rTwo.bottom = Object->GetY() + Object->GetHeight();

// TEST IF THE BOUNDING BOXES INTERSECT

	if (IntersectRect(&rOverlap, &rOne, &rTwo))
	{
// FILL IN OVERLAP RECTANGLE INFORMATION

// FIRST ONE

		rOneOverlap.top = rOverlap.top - rOne.top;
		rOneOverlap.bottom = rOverlap.bottom - rOne.top;
		rOneOverlap.left = rOverlap.left - rOne.left;
		rOneOverlap.right = rOverlap.right - rOne.left;
// SECOND ONE

		rTwoOverlap.top = rOverlap.top - rTwo.top;
		rTwoOverlap.bottom = rOverlap.bottom - rTwo.top;
		rTwoOverlap.left = rOverlap.left - rTwo.left;
		rTwoOverlap.right = rOverlap.right - rTwo.left;

// FILL IN WIDTH AND HEIGHT OF OVERLAPPING AREA

		overlapWidth = rOverlap.right - rOverlap.left - 1;
		overlapHeight = rOverlap.bottom - rOverlap.top - 1;

// LOCK SURFACES AND GET THEIR PITCH AND SURFACE

// LOCK SURFACE ONE

		surfaceone = Player->CurrBitmap->GetSurface();
		surfaceone->Lock(&rOneOverlap, &ddsdBlank, DDLOCK_WAIT | DDLOCK_READONLY, 0);
		pixel1 = (UINT *)ddsdBlank.lpSurface;
		int oneWidth = ddsdBlank.lPitch;
// LOCK SURFACE TWO

		surfacetwo = Object->GetSurface();
		DDraw->GetSurface(BACK_BUFFER)->Blt(&temp, surfacetwo, &rTwoOverlap, DDBLT_WAIT | DDBLT_KEYSRC, 0);
		surfacetwo->Lock(&rTwoOverlap, &ddsdBlank, DDLOCK_WAIT | DDLOCK_READONLY, 0);
		pixel2 = (UINT *)ddsdBlank.lpSurface;
		twoWidth = ddsdBlank.lPitch;

// LOOP THROUGH AND COMPARE THEIR PIXEL VALUES TO THE COLORKEY

		for (i = 0; i < overlapWidth; i++)
		{
			for (j = 0; j < overlapHeight; j++)
			{
				if (pixel1[i + onex + (j + oney) * oneWidth] != ColorKey
					&& pixel2[i + twox + (j + twoy) * twoWidth] != ColorKey)
				{
					Console.AddMessage("Collision occurred!");

					iscollision = true;
					break;
				}
			}
			if (iscollision)
				break;
		}
// UNLOCK THE SURFACES

		surfaceone->Unlock(&rOneOverlap);
		surfacetwo->Unlock(&rTwoOverlap);
// THERE IS A COLLISION

		if (iscollision)
			return 1;
	}
// NO COLLISION!

	return 0;
}
          
What am I doing wrong? I can see it's checking the correct RECTs and stuff, but it returns the first time through the loop! Help! [edited by - apollyon on June 9, 2002 5:19:26 PM] [edited by - apollyon on June 10, 2002 6:28:36 PM]
Advertisement
I don''t think I''m going to waste my time trudging though all that code with out any comments, spaces between the lines, and hardly any modularity.

It will make your life (and others looking at your code) much easier if you add comments while you write, declare all variables at the top of the function (or block atleast), and have some spaces between lines for God''s sake.

Other than that, this problem is a simple logic problem which you should solve yourself instead of asking us to do your work for you.

Breakpoints, Breakpoints, and more Breakpoints.

Nutts

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)

Um, yeah, I explained that it the first time it goes through the loop it kills itself. Maybe you should learn to read, moron. I apologize for the lack of comments, but that''s not the case. I determined what the problem is, and I don''t know how to go about fixing it. When I compare the pixel to the color key, it automatically says it''s the same. The hostility you''ve expressed does wonders for your character, dude. You could''ve at least attempted to read it.
Wasn''t trying to be hostile, but when you offer up code for people to debug for you, you should try and make it as easy as possible for them to do so.

Besides, I really don''t have the time to look through your code and debug it for you. I can offer 1 suggestion (I''ve done pixel-per-pixel collision too): Don''t Lock and Unlock the surface, it''s too slow. Instead, store seperate masks for each image with one bit-per-pixel. It will do wonders for your speed.

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)

Some pixel collision stuff
Bits and pieces from my sprite engine ( 16 bit stuff ).

_____________________________________________________________
// make an array to hold the bitmask
BOOL *source_bitmask;
source_bitmask = new BOOL [ surface_width * surface_height ];

_____________________________________________________________

We have to set up a bitmask for the surface.
The pixel data will be copied onto the above array as BOOL.


  void SPRITE::Load_Bitmask(){   int fb_cnt = 0;  USHORT *surf_ptr; // A pointer to the surface    DDSURFACEDESC2  ddsd;       ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2));  ddsd.dwSize = sizeof(ddsd); // Load size    // Lock the surface  ( surface ) -> Lock( NULL,                       &ddsd,                       DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,                       NULL);  // Get a pointer to surface   surf_ptr = (USHORT *)ddsd.lpSurface;      // Load the bitmask looping through the surface  for ( DWORD i = 0 ;  i < surface_height ; i++ )      { for ( DWORD j = 0 ; j < surface_width ; j++ )           {              // Calculate position in array             fb_cnt = ( ( i  *  surface_width ) + j );             // If the value is not 0, set the BOOL to TRUE             source_bitmask [ fb_cnt ] = ( *surf_ptr != 0 ) ? TRUE : FALSE;             // Increment the surface pointer             surf_ptr++;           }         }    // Unlock the surface   ( surface ) -> Unlock(NULL);}// end Load_Bitmask  


_____________________________________________________________


Now we have to test for a collision
I made this a global fuction and made it a friend to my sprite class. This is rather bulky code, but it was written for animated and non-animated sprites. I hope you can follow it.



  short int Sprite_Sprite_Collide( SPRITE *ptr_1, SPRITE *ptr_2 ){  int     sp_width_1 = ptr_1 -> width;  int     sp_width_2 = ptr_2 -> width;    RECT    frame_1,          frame_2;  int     frame_offset_1,   frame_offset_2;  int     over_left, over_right;  int     over_top,  over_bottom;;  int     over_width,over_height;  int     i, j;  int     y1_offset,        y2_offset;  BOOL    *P_p1, *P_p2;     // Quick Reject Stuff  if ( ptr_1 -> dest_rect.bottom < ptr_2 -> dest_rect.top    ) return(0);  if ( ptr_1 -> dest_rect.top    > ptr_2 -> dest_rect.bottom ) return(0);  if ( ptr_1 -> dest_rect.right  < ptr_2 -> dest_rect.left   ) return(0);  if ( ptr_1 -> dest_rect.left   > ptr_2 -> dest_rect.right  ) return(0);  // Get the overlapping rectangle  if ( ptr_1 -> dest_rect.bottom > ptr_2 -> dest_rect.bottom )        over_bottom = ptr_2 -> dest_rect.bottom;  else over_bottom = ptr_1 -> dest_rect.bottom;  if ( ptr_1 -> dest_rect.top < ptr_2 -> dest_rect.top )       over_top = ptr_2 -> dest_rect.top;  else over_top = ptr_1 -> dest_rect.top;  if ( ptr_1 -> dest_rect.right > ptr_2 -> dest_rect.right )       over_right = ptr_2 -> dest_rect.right;  else over_right = ptr_1 -> dest_rect.right;  if ( ptr_1 -> dest_rect.left < ptr_2 -> dest_rect.left )       over_left = ptr_2 -> dest_rect.left;  else over_left = ptr_1 -> dest_rect.left;    // Calculate frame offsets for object 1  frame_1.left   = ( over_left   - (int)ptr_1 -> x_pos );  frame_1.top    = ( over_top    - (int)ptr_1 -> y_pos );  frame_1.right  = ( over_right  - (int)ptr_1 -> x_pos );  frame_1.bottom = ( over_bottom - (int)ptr_1 -> y_pos );  frame_offset_1 = ( frame_1.top * sp_width_1 ) + frame_1.left;    if ( ptr_1 -> animated == TRUE )     { frame_offset_1 += ( ptr_1 -> source_rect.top * sp_width_1 ) +                           ptr_1 -> source_rect.left;      }    // Calculate frame offsets for object 2  frame_2.left   = ( over_left   - (int)ptr_2 -> x_pos );  frame_2.top    = ( over_top    - (int)ptr_2 -> y_pos );  frame_2.right  = ( over_right  - (int)ptr_2 -> x_pos );  frame_2.bottom = ( over_bottom - (int)ptr_2 -> y_pos );  frame_offset_2 = ( frame_2.top * sp_width_2 ) + frame_2.left;    if ( ptr_2 -> animated == TRUE )     { frame_offset_2 += ( ptr_2 -> source_rect.top * sp_width_2 ) +                           ptr_2 -> source_rect.left;      }    // The size of the overlapping rectangle  over_width  = abs( over_right  - over_left );  over_height = abs( over_bottom - over_top  );      // Loop through the bitmask checking for TRUE in  // both of the objects bitmasks.  for ( i = 0 ; i < over_height ; i ++ )      {   y1_offset = ( i * sp_width_1 ) + frame_offset_1;          y2_offset = ( i * sp_width_2 ) + frame_offset_2;         P_p1 = &ptr_1 -> source_bitmask [ y1_offset ];         P_p2 = &ptr_2 -> source_bitmask [ y2_offset ];         for ( j = 0 ; j < over_width ; j++, P_p1++, P_p2++ )             {                 if ( ( *P_p1 == TRUE ) && ( *P_p2 == TRUE ) )                    { ptr_1 -> pixel_hit = y1_offset + j;                      ptr_2 -> pixel_hit = y2_offset + j;                      return(1); }             }// end for j      }// end for i  return(0);}// end Sprite_Sprite_Collide  


Well that''s how I did it. I re-wrote John Amatos collision algos with bitmasks. If find the collision detection rather quick.

Guy

This topic is closed to new replies.

Advertisement