   pixel perfect collision (almost?)
  EDIT: WHoops! I forgot to tell you.  This game is made using DarkGDK, MS Visual C++, and DirectXHey everyone, I've been working on trying to get this pixel perfect collision function to work for days and I can't seem to get it.  I can only get pixel perfect when I move a sprite into the top left quadrant of another sprite, everywhere else is kinda weird.NOTE:  All sprite coordinates are at top left corner of sprite.  So when I say dbSprite(i, 1);  this will move sprite with ID "i" to the right 1 pixelHere is the beta version of "Pixel Perfect Collisions"Headers/Prototypes#include "DarkGDK.h"#include &lt;vector&gt;#if _MSC_VER &gt; 1020   // if VC++ version is &gt; 4.2   using namespace std;  // std c++ libs implemented in std   #endifbool BuildSpriteMask(int s1, vector&lt;int&gt; &v);bool PixelCollision( int s1, int s2 );Mainvoid DarkGDK ( void ){// when starting a Dark GDK program it is useful to set global// application properties, we begin by turning the sync rate on,// this means we control when the screen is updated, we also set// the maximum rate to 60 which means the maximum frame rate will// be set at 60 frames per seconddbSyncOn   ( );dbSyncRate ( 60 );// a call is made to this function so we can stop the GDK from// responding to the escape key, we can then add in some code in our// main loop so we can control what happens when the escape key is presseddbDisableEscapeKey ( );dbLoadImage ( "land.bmp", 1 );dbSprite ( 1, 0, 0, 1 );dbLoadImage("collisionTXT.bmp", 3);dbLoadImage ("circle1.bmp", 4);dbLoadImage("circlePlayer.bmp",2);    dbSprite (4, 300, 100, 4);dbSprite(3,0,0,3);dbSprite ( 2,0, 0, 2 );// now we come to our main loop, we call LoopGDK so some internal// work can be carried out by the GDKwhile ( LoopGDK ( ) ){if(dbRightKey() == 1){dbRotateSprite(2,90);dbMoveSprite(2,1);dbRotateSprite(2,0);}if(dbLeftKey() == 1){dbRotateSprite(2,270);dbMoveSprite(2,1);dbRotateSprite(2,0);}if(dbUpKey()){dbMoveSprite(2,1);}if(dbDownKey()){dbRotateSprite(2,180);dbMoveSprite(2,1);dbRotateSprite(2,0);}if(PixelCollision(2,4)){dbShowSprite(3);}else{dbHideSprite(3);}if ( dbEscapeKey ( ) )break;dbSync();// here we make a call to update the contents of the screen}// when the user presses escape the code will break out to this location// and we can free up any previously allocated resources// delete all the spritesfor(int i = 1; i &lt; 5; i++)dbDeleteSprite ( i );// delete the backdrop imagedbDeleteImage ( 1 );// and now everything is ready to return back to Windowsreturn;}Sprite Maskbool BuildSpriteMask(int s1, vector&lt;int&gt; &v){  bool result = FALSE;  LPDIRECT3DTEXTURE9 pTexture = dbGetImagePointer(s1);  // Lock the texture:  D3DLOCKED_RECT rect;  HRESULT hResult = pTexture-&gt;LockRect(0, &rect, NULL, D3DLOCK_READONLY);  if(FAILED(hResult))  {    // Failed to lock the texture, error    return 0;  }  // Get the bits as a BYTE*  const BYTE* pBits = (BYTE*)rect.pBits;  // Seek to the correct pixel and read it  DWORD nBytesPerPixel = 4;  const DWORD* pPixel = 0;  // (DWORD*)(pBits + y * rect.Pitch + x*nBytesPerPixel);  //DWORD dwPixel = *pPixel;   int sh = dbSpriteHeight(s1);  int sw = dbSpriteWidth(s1);  for(int y = 0; y &lt; sh; y++)  {    for(int x = 0; x &lt; sw; x++)    { /* NOTE: I'm a little rusty on my math, but it should just be the same as before */ pPixel = (DWORD*)(pBits + y * rect.Pitch + x*nBytesPerPixel); if( *pPixel == D3DCOLOR_XRGB(255,0,255)) {   v.push_back(0); } else {   v.push_back(1); }    }  }  // Unlock the texture  pTexture-&gt;UnlockRect(0);  return result;}Pixel Collisionbool PixelCollision( int s1, int s2 ){  /*Load the Sprite1/Sprite2 variables into local memory so that we    can avoid the extra overhead required for multiple calls to the    related GDK calls. Functions are slower than memory reads, so    we want to call them as few times as possible...  */  int s1x=dbSpriteX(s1);  int s1y=dbSpriteY(s1);  int s1w=dbSpriteWidth(s1);  int s1h=dbSpriteHeight(s1);  int s2x=dbSpriteX(s2);  int s2y=dbSpriteY(s2);  int s2w=dbSpriteWidth(s2);  int s2h=dbSpriteHeight(s2);  int s1x2 = s1x+s1w;   int s1y2 = s1y+s1h;  int s2x2 = s2x+s2w;  int s2y2 = s2y+s2h;  /* Calculates the intersection rectangle between the two sprites */   int minX = max(s1x, s2x);  int maxX = min(s1x2, s2x2);  int minY = max(s1y, s2y);  int maxY = min(s1y2, s2y2);  /*if our instersection rect's Width is greater than the combined    widths of both sprites, then no collision could have taken    place since there would be at least one pixel between both    sprites  */  if (s1x2 &lt; s2x || s2x2 &lt; s1x)    return false;   /*Similarly, if our instersection rect's height is greater than    the combined heights of both sprites, then no collision couldhave taken place since there would be at least one pixel betweenboth sprites  */  if (s1y2 &lt; s2y || s2y2 &lt; s1y)    return false;  /*Now we know that there is still a potential for collision. In    order to find out for sure, we have to test every pixel between    both sprites that fall within the intersection rect - we can    ignore all of the others.  */  /*    First, we have to build the sprite masks of the images. To    gain a performance boost, we wait until this point to actually    build them because there was possibilities of no collisions    that could be eliminated before wasting time reading video    memory. Alas, we can't put it off any longer...    Note: Ideally, the sprite masks would be built just once and    stored in memory so that repeated calls to BuildSpriteMask()    wouldn't be necessary...  */  vector&lt;int&gt; spriteOneVect;  vector&lt;int&gt; spriteTwoVect;  /*We place a single call to BuildSpriteMask() for each sprite    so that we only have to lock the video memory once instead of    once for each pixel...  */  BuildSpriteMask(  s1, spriteOneVect);  BuildSpriteMask(  s2, spriteTwoVect);  /* Now that the sprite masks are built, let's test them */    /*FIRST: check to see what direction we are coming from   Think of this in quadrants (We'll start in the top left,   then to top right, then bottom left, then bottom right*/  int s1XAP;int s1YAP;int s2XAP;int s2YAP; for(int currentY = minY; currentY &lt; maxY; currentY++) { s1YAP = currentY - s1y; s2YAP = currentY - s2y;for(int currentX = minX; currentX &lt; maxX; currentX++){s1XAP = currentX - s1x;s2XAP = currentX - s2x;if(spriteOneVect[s1XAP*s1YAP] == spriteTwoVect[s2XAP*s2YAP] && spriteOneVect[s1XAP*s1YAP] == 1)return true;} }  return false;}[Edited by - dhardin on April 4, 2010 1:06:18 PM]
  I went through and tested most of the code out.  I'm pretty sure the function for creating the bitmap is correct, if it is, then I'm 90% sure my error is in the last set of nested for loops.EDIT:  I just tested the bitmasks.  I did this by creating an output file and just writing the desired colors as 1's and the others as 0's.  Both bitmasks were created flawlessly.[Edited by - dhardin on April 4, 2010 2:08:11 PM];  It looks like you aren't looking up the pixels in the masks correctly.Instead of spriteOneVect[s1XAP*s1YAP], something like spriteOneVect[s1XAP+sprite1width*s1YAP]   ;  I'd check that the collision mask is what you think it is first. The easiest way is to use 0 instead of D3DLOCK_READONLY, and then set the pixel to 0x00000000 if it's not collidable, or 0xffffffff if it is. Then when you render the sprite, you'll be able to clearly see what your code thinks the collision mask is.If the collision mask is ok, then you can start looking at the actual collision function.   ;  Thanks guys, I just got it late last night.I posted the files herehttp://forum.thegamecreators.com/?m=forum_view&t=168273&b=22Yep, and it was indeed the way I was looking up the pixels in the collision function!  Bitmasks were created flawlessly (I had them exported to text file as a picture of 1's and 0's).  But it works great now!  Thanks everyonep.s. Steve, thanks for posting your get pixel colors online.  I could not have done this without that function.   