title: Per-pixel collision problem in C#
body: <p>I am writing a small 2d game engine in C# for my own purposes, and it works fine except for the sprite collision detection. I've decided to make it a per-pixel detection (easiest for me to implement), but it is not working the way it's supposed to. The code detects a collision long before it happens. I've examined every component of the detection, but I can't find the problem.</p>
  
  <p>The collision detection method:</p>
  
  <pre><code>public static bool CheckForCollision(Sprite s1, Sprite s2, bool perpixel) {
      if(!perpixel) {
          return s1.CollisionBox.IntersectsWith(s2.CollisionBox);
      }
      else {
          Rectangle rect;
          Image img1 = GraphicsHandler.ResizeImage(GraphicsHandler.RotateImagePoint(s1.Image, s1.Position, s1.Origin, s1.Rotation, out rect), s1.Scale);
          int posx1 = rect.X;
          int posy1 = rect.Y;
  
          Image img2 = GraphicsHandler.ResizeImage(GraphicsHandler.RotateImagePoint(s2.Image, s2.Position, s2.Origin, s2.Rotation, out rect), s2.Scale);
          int posx2 = rect.X;
          int posy2 = rect.Y;
  
          Rectangle abounds = new Rectangle(posx1, posy1, (int)img1.Width, (int)img1.Height);
          Rectangle bbounds = new Rectangle(posx2, posy2, (int)img2.Width, (int)img2.Height);
  
          if(Utilities.RectangleIntersects(abounds, bbounds)) {
  
              uint[] bitsA = s1.GetPixelData(false);
  
              uint[] bitsB = s2.GetPixelData(false);
  
              int x1 = Math.Max(abounds.X, bbounds.X);
              int x2 = Math.Min(abounds.X + abounds.Width, bbounds.X + bbounds.Width);
  
              int y1 = Math.Max(abounds.Y, bbounds.Y);
              int y2 = Math.Min(abounds.Y + abounds.Height, bbounds.Y + bbounds.Height);
  
              for(int y = y1; y &lt; y2; ++y) {
                  for(int x = x1; x &lt; x2; ++x) {
                      if(((bitsA[(x - abounds.X) + (y - abounds.Y) * abounds.Width] &amp; 0xFF000000) &gt;&gt; 24) &gt; 20 &amp;&amp;
                          ((bitsB[(x - bbounds.X) + (y - bbounds.Y) * bbounds.Width] &amp; 0xFF000000) &gt;&gt; 24) &gt; 20)
                          return true;
                  }
              }
          }
          return false;
      }
  }
  </code></pre>
  
  <p>The image rotation method:</p>
  
  <pre><code>internal static Image RotateImagePoint(Image img, Vector pos, Vector orig, double rotation, out Rectangle sz) {
      if(!(new Rectangle(new Point(0), img.Size).Contains(new Point((int)orig.X, (int)orig.Y))))
          Console.WriteLine("Origin point is not present in image bound; unwanted cropping might occur");
      rotation = (double)ra_de((double)rotation);
      sz = GetRotateDimensions((int)pos.X, (int)pos.Y, img.Width, img.Height, rotation, false);
      Bitmap bmp = new Bitmap(sz.Width, sz.Height);
      Graphics g = Graphics.FromImage(bmp);
      g.SmoothingMode = SmoothingMode.AntiAlias;
      g.InterpolationMode = InterpolationMode.HighQualityBicubic;
      g.PixelOffsetMode = PixelOffsetMode.HighQuality;
      g.RotateTransform((float)rotation);
      g.TranslateTransform(sz.Width / 2, sz.Height / 2, MatrixOrder.Append);
      g.DrawImage(img, (float)-orig.X, (float)-orig.Y);
      g.Dispose();
      return bmp;
  }       
  internal static Rectangle GetRotateDimensions(int imgx, int imgy, int imgwidth, int imgheight, double rotation, bool Crop) {
      Rectangle sz = new Rectangle();
      if (Crop == true) {
          // absolute trig values goes for all angles
          double dera = de_ra(rotation);
          double sin = Math.Abs(Math.Sin(dera));
          double cos = Math.Abs(Math.Cos(dera));
          // general trig rules:
          // length(adjacent) = cos(theta) * length(hypotenuse)
          // length(opposite) = sin(theta) * length(hypotenuse)
          // applied width = lo(img height) + la(img width)
          sz.Width = (int)(sin * imgheight + cos * imgwidth);
          // applied height = lo(img width) + la(img height)
          sz.Height = (int)(sin * imgwidth + cos * imgheight);
      }
      else {
          // get image diagonal to fit any rotation (w &amp; h =diagonal)
          sz.X = imgx - (int)Math.Sqrt(Math.Pow(imgwidth, 2.0) + Math.Pow(imgheight, 2.0));
          sz.Y = imgy - (int)Math.Sqrt(Math.Pow(imgwidth, 2.0) + Math.Pow(imgheight, 2.0));
          sz.Width = (int)Math.Sqrt(Math.Pow(imgwidth, 2.0) + Math.Pow(imgheight, 2.0)) * 2;
          sz.Height = sz.Width;
  
      }
      return sz;
  }
  </code></pre>
  
  <p>Pixel getting method:</p>
  
  <pre><code>public uint[] GetPixelData(bool useBaseImage) {
      Rectangle rect;
      Image image;
      if (useBaseImage)
          image = Image;
      else
          image = GraphicsHandler.ResizeImage(GraphicsHandler.RotateImagePoint(Image, Position, Origin, Rotation, out rect), Scale);
  
      BitmapData data;
      try {
          data = ((Bitmap)image).LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
      }
      catch (ArgumentException) {
          data = ((Bitmap)image).LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, image.PixelFormat);
      }
  
      byte[] rawdata = new byte[data.Stride * image.Height];
      Marshal.Copy(data.Scan0, rawdata, 0, data.Stride * image.Height);
      ((Bitmap)image).UnlockBits(data);
      int pixelsize = 4;
      if (data.PixelFormat == PixelFormat.Format24bppRgb)
          pixelsize = 3;
      else if (data.PixelFormat == PixelFormat.Format32bppArgb || data.PixelFormat == PixelFormat.Format32bppRgb)
          pixelsize = 4;
  
      double intdatasize = Math.Ceiling((double)rawdata.Length / pixelsize);
      uint[] intdata = new uint[(int)intdatasize];
  
      Buffer.BlockCopy(rawdata, 0, intdata, 0, rawdata.Length);
  
      return intdata;
  } 
  </code></pre>
  
  <p>The pixel retrieval method works, and the rotation method works as well, so the only place that the code might be wrong is the collision detection code, but I really have no idea where the problem might be.</p>