I'm been developing my own physics engine for a school project and recently I encountered a problem: Per pixel collisions on big sprites make my FPS drop A LOT.
Here's my pixel collision code. Before entering the following code I'm using Intersects() to see if their bounding boxes collided.
private bool PerPixelCollision(IObject a, IObject b) { Color[] bitsA = new Color[a.Texture.Width * a.Texture.Height]; a.Texture.GetData(bitsA); Color[] bitsB = new Color[b.Texture.Width * b.Texture.Height]; b.Texture.GetData(bitsB); // Calculate the intersecting rectangle int x1 = Math.Max(a.Bounds.X, b.Bounds.X); int x2 = Math.Min(a.Bounds.X + a.Bounds.Width, b.Bounds.X + b.Bounds.Width); int y1 = Math.Max(a.Bounds.Y, b.Bounds.Y); int y2 = Math.Min(a.Bounds.Y + a.Bounds.Height, b.Bounds.Y + b.Bounds.Height); Color c; Color d; // For each single pixel in the intersecting rectangle for (int y = y1; y < y2; ++y) { for (int x = x1; x < x2; ++x) { // Get the color from each texture c = bitsA[(x - a.Bounds.X) + (y - a.Bounds.Y) * a.Texture.Width]; d = bitsB[(x - b.Bounds.X) + (y - b.Bounds.Y) * b.Texture.Width]; if (c.A != 0 && d.A != 0) // If both colors are not transparent (the alpha channel is not 0), then there is a collision { return true; } } } // If no collision occurred by now, we're clear. return false; } In the example I'm using to test I'm dropping 4 sprites in another sprite that represents the floor (736x79). When I change the sprite that represents the floor to a bigger sprite (3600x270) the FPS drops. I know the problem is in the pixel collision because I'm using a profiler.
Does anyone have any idea on how to optimize the collision?
P.S.: Sorry if I wasn't clear enough about my problem. My english is not so good.
EDIT: The first problem was solved by using the solution provided by @pinckerman but I found another one related to pixel collision detection. When a sprite collide with a the transparent part of a texture, we get the part that intersected and check all the pixels of that part. The problem is: When the transparent part is big enough to cover the whole sprite, I check the whole texture of that sprite (currently using 50x50 textures which is 2500 pixels). Is there any way to not check the whole texture?
Thanks
GetData()on a texture stalls the rendering pipeline, which prevents the GPU and CPU from working together at maximum efficiency. In most cases it's going to be better to use geometric collision detection--though of course, there's nothing wrong with this sort of thing as a learning exercise. See this article for more information.