2

I've stumbled upon a problem while working on my simple game and have been stuck on it for quite a while, I hope anyone can offer me an elegant solution or a step into the right direction.

I currently have a simple top down scroller, the player is for now just a white cube, and around the map are rotating 45 degree light cones made with Krypton. The player has to avoid being seen by the lights, so I'm trying to create a pixel-collision method to fire an event for when the player falls in range of the lit up area.

Krypton has a property that returns the bounding rectangle around a light, but I can't use that for the collision since it will draw a huge square around the entire zone of the light, so the player would get detected even if you stand behind the light. I want accuracy.

I've also tried drawing a triangle around the lit up area, but the problem here was it wasn't as accurate as I would want it to be, because some of the light shines through corridors, which I can't accurately pick up with a static triangle, plus the triangle goes through walls since the range of the light is actually larger than half the map, but is mostly just blockaded by shadow hulls. The player has to be able to hide from said lights behind walls. Here's an image example of what I mean. Image

So I figured the best way to do this would be to check if the color of one of the pixels of the player has changed to a certain .. RGB value. This would require some hard coding but it's a simple game, so I would not mind this approach. But here I run into some trouble.

I read about the Texture2D.GetData<> method, I can do this however it returns a color array of the actual imported texture, which is always white. It doesn't return the post-processed results. Which makes sense because there can be multiple textures in the scene.

The next one I tried was GraphicsDevice.GetBackBufferData<> which returns all the pixels of the viewport, which immediately brings my FPS down to none, there's overloads to only retrieve pixels in a certain range but they never seem to work for me, as I'm always surprised with the out of index exception. Here's what I try when using this method:

Color[] colors = new Color[10]
GraphicsDevice.GetBackBufferData<Color(colors, 0, 10);

(Just an example, but I can't seem to understand why this does not work.)

So to cut to the chase more or less, I'm looking for a method to retrieve a color array of a certain area or coordinate of my view port, so I can compare all the colors in said array to see if they match.

Apologies if it's a bit long, but I would greatly appreciate any advice or guidance as I don't know what I'm missing, I've followed most tutorials regarding this and they all seem to compare the color values of the textures two colliding textures, but if I'm not mistaken the texture itself never actually changes colors, since it's just an imported asset that gets drawn. I figure I need to retrieve the colors of WHERE the texture is drawn to properly check if there has been a change.

Kind regards

EDIT:

I got it to work, the rectangle as argument in GetBackBufferData works well, disabling MultiSampling makes the lag non existent. Thank you for the suggestions, @Bjarke Søgaard and @thomas88wp.

Color colorArray = new Color[player.Bounds.Width * player.Bounds.Height];
Color[] colors = new Color[player.Bounds.Width * player.Bounds.Height];
GraphicsDevice.GetBackBufferData<Color>(rec, colors, 0, colors.Count());
Stella
  • 498
  • 4
  • 15
  • 1
    I've never had to accomplish anything like this, so the only solution I would suggest, would be to use a RenderTarget. But the process I'm thinking of, sounds very similar to that of GetBackBufferData<>. Basically render everything to a rendertarget, and use this to get pixels from. But this is probably the same as the GraphicsDevice one. – Falgantil May 25 '14 at 14:16
  • I agree that the above might work better. Also, if you're going to use your method, I would use the third overload if GetBackBufferData and pass it a Rect where your character is rendered. Just make sure that your array is the correct size (width * height of the rect). This seems a very work-around way to go about it, though. Sure there's not something easier? – thomas88wp May 25 '14 at 15:36
  • I really appreciate your input, I added a rectangle property to my player class, which I pass through to GetBackBufferData, as suggested. This seems to work, I am getting the correct colors of my character sprite. So a bit more tinkering seemed to have worked, however the rectangle is merely 35*35 pixels and my fps still drops to about 5 whenever I run the method, which I find odd. Other games often use pixel collision methods for multiple objects, while I just iterate through 1225 pixels. Think there's anything to remedy this? Either way I thank you for your time. – Stella May 25 '14 at 18:15
  • I'm PRETTY sure that most games doesn't actually loop through all pixels. Possibly simply the border of said image. Either that, or they keep track of each pixel (again, only on the border) and tests with that. That way you'll only be looping through all of the pixels that actually matters, and you wouldn't be reading (and as such, also parsing them) every time you loop through the pixels. Notice that looping through pixels every frame is a lot harder than just saving the collection of Vector2's and looping through those instead. – Falgantil May 26 '14 at 10:04
  • You're right! However I'm not iterating through all the pixels in my back buffer. (As far as I'm concerned) I'm retrieving a 35*35 rectangle from it which I loop through. It's still more than the average properly-coded game and more than just scanning the boundaries, but I'll think of ways to improve this down the road. I'm satisfied for now. – Stella May 26 '14 at 13:29

0 Answers0