I'm curious.. I've been working on creating just a platformer testbed so that I can start learning cameras and pixel perfect collision. I incorporated the pixel perfect collision sample from Ziggy's site and am trying to figure out how to do displacement so that if the sprite collides, it will simply move itself out of a collision state in the appropriate direction. Right now the routines first test the bounding boxes and then if those intersect or touch, it does a pixel perfect collision test (which is slow, but if I load the GetData info during a loading screen it would be quicker I think). Now this will flag the collisions perfectly but I can not figure out how to tell 'where' the collision occurred and how many pixels to move it in which direction to clear the collision. :(
Right now I have added in gravity, velocity and basic friction / deceleration on the X axis. I'm also trying not to use tiles as I do not want the old flat runs and 45 degree slopes, etc. I want the sprite to follow the terrain. I was looking at the code from a platformers demo on ziggyware that had a function called calculateminimumtranslationdistance that took 2 boundingboxes and returned a vector2, which seemed like the right thing to use.. but thats based off the boundingboxes, not the pixel perfect collision, plus I have never used this boundingbox class and I know it uses a vector3 which I dont know which all values to use.
So I'm stuck! Help please?
So assuming I have a playerVelcity, playerGravity, and playerPosition Vector2's, how would I change this to determine where the collision occured, top bottom left or right, and then figure out a displacement vector2 that could be added to the playerPosition to resolve the collision? Here's the relevant code:
| // this is hacked together so a lot of stuff is hardcoded which will all be cleaned up later.. |
| |
| Vector2 playerPosition, playerVelocity, playerGravity; |
| |
| |
| // this just passes the texture2d 's for now |
| if (Intersects(player, platform1)) |
| { |
| playerColor = Color.Red; |
| } |
| else playerColor = Color.White; |
| |
| |
| // this does the pixel perfect test. It first checks the Collision.Intersects method which takes the bounding boxes |
| // and determines if they intersect or touch. |
| public bool Intersects(Texture2D a, Texture2D b) |
| { |
| |
| playerBoundingBox = new Rectangle((int)playerPosition.X, (int)playerPosition.Y, a.Width, a.Height); |
| platformBoundingBox = new Rectangle(247, 209, 259, 20); |
| |
| if (Collision.Intersects(playerBoundingBox, platformBoundingBox)) |
| { |
| |
| uint[ bitsA = new uint[a.Width * a.Height]; |
| a.GetData<uint>(bitsA); |
| |
| uint[ bitsB = new uint[b.Width * b.Height]; |
| b.GetData<uint>(bitsB); |
| |
| int x1 = Math.Max(playerBoundingBox.X, platformBoundingBox.X); |
| int x2 = Math.Min(playerBoundingBox.X + playerBoundingBox.Width, platformBoundingBox.X + platformBoundingBox.Width); |
| |
| int y1 = Math.Max(playerBoundingBox.Y, platformBoundingBox.Y); |
| int y2 = Math.Min(playerBoundingBox.Y + playerBoundingBox.Height, platformBoundingBox.Y + platformBoundingBox.Height); |
| |
| for (int y = y1; y < y2; ++y) |
| { |
| for (int x = x1; x < x2; ++x) |
| { |
| if (((bitsA[(x - playerBoundingBox.X) + (y - playerBoundingBox.Y) * a.Width] & 0xFF000000) >> 24) > 20 && |
| ((bitsB[(x - platformBoundingBox.X) + (y - platformBoundingBox.Y) * b.Width] & 0xFF000000) >> 24) > 20) |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
Link to Full Project Download Here.
Note this a XNA 3.0 CTP Project and only the topmost centerish platform is tested and acted upon.