Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Is this possible?

To elaborate, I am making a PacMan offshoot. Essentially it is a "zoomed in" version of the game, but the board is randomly generated. I have 11 .png files each to be used as a background for different hallway shapes. You have your straightaways, corners T junctions and cross intersection. They are very simple, each has a black background and the walls are blue. What I am looking for is a way to stop the player from walking on the blue parts of each image. Is that possible?

My current set-up is that I have a Piece class that holds the image, Entry points as bools (up down left right) for when I randomly select the image to be used so that a path can be created, size, etc. I then have a Board class that holds a list of Pieces (size 11 (One for each image))) and then 2D an array "board" (currently 9x9) that randomly but intelligently generates the map. When it comes to player pathing, I was manually going to add to the Piece class code that adds invisible rectangles over the blue walls and then have the Player class, or some other class, check for collision. This would take a ton of extra code because each image is different so each would need to be manually done.

I was just thinking there must be an easier way to do this, and the whole color idea occurred to me. If i could just check if it intersects the blue and then change its position back that would be much easier.

I am at work currently, but if there is any code you would need to see, or any other helpful information let me know and I will add it as soon as I get home!

TL;DR Is there a way to check collision via color, or add rectangle automatically over a specific color.

share|improve this question
    
    
@Byte56 what I'm gathering from that thread, is that I was on the right track doing the bounding boxes? The biggest issue between that thread and my question is that I'm not dealing with any specific objects to check collision against, Its just a background image that will scroll to the next tile as you move and will contain three or more walls. These images take up the whole screen so there would be a lot of extra work to do it that way. If that is the best option though, I am more than willing to do it the way I originally planned. I hope that helps clarify a bit. –  Nick Jan 15 at 2:40
    
It's possible to do it both ways. You may find the alternative to be more work, but you may also find it to be worth it performance wise. I suggest you try it the easy way first, then move on to the more challenging way if you find the performance lacking. –  Byte56 Jan 15 at 3:04

1 Answer 1

An option would be to process the images once, when they are loaded. Grab the pixel data, and process it to determine the smallest Rectangle that encompasses all the pixels of a specific color.

This isn't a pixel perfect collision, but it will help with processing your images, and getting collision boxes for you.

You can further optimize this by storing the bounds in a data file, instead of running it every time you execute the binary. But if you just do it during your game load phase, it should be relatively fast, considering you have a relatively small number of images to process.

//Get smallest rectangle from Texture, cased on color
Rectangle GetSmallestRectangleFromTexture(Texture2D Texture, Color color)
{
    //Create our index of sprite frames
    Color[,] Colors = TextureTo2DArray(Texture);

    //determine the minimum bounds
    int x1 = 9999999, y1 = 9999999;
    int x2 = -999999, y2 = -999999;

    for (int a = 0; a < Texture.Width; a++)
    {
        for (int b = 0; b < Texture.Height; b++)
        {
            //If we find a color match, update bounds if needed
            if (Colors[a, b] == color)
            {
                if (x1 > a) x1 = a;
                if (x2 < a) x2 = a;

                if (y1 > b) y1 = b;
                if (y2 < b) y2 = b;
            }
        }
    }

    //We now have our smallest possible rectangle for this texture
    return new Rectangle(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
}

//convert texture to 2d array
Color[,] TextureTo2DArray(Texture2D texture)
{
    //Texture.GetData returns a 1D array
    Color[] colors1D = new Color[texture.Width * texture.Height];  
    texture.GetData(colors1D);  

    //convert the 1D array to 2D for easier processing
    Color[,] colors2D = new Color[texture.Width, texture.Height]; 
    for (int x = 0; x < texture.Width; x++) 
        for (int y = 0; y < texture.Height; y++)
            colors2D[x, y] = colors1D[x + y * texture.Width];

    return colors2D; 
}

This is not exactly what you are asking, but I think this could help you.

Edit: Write up a blog post about this: http://www.jgallant.com/auto-calculating-bounding-box-from-texture-in-monogame-xna/

share|improve this answer
    
This doesn't quite solve my issue. I will need many rectangles because not all of the blue touches. for example on a intersection the four corners are blue squares and the rest is black, giving the look of a hallway or road intersection. I might be able to work off of this however! –  Nick Jan 17 at 0:02
    
@Nick Another idea would be to use the Rectangle as a first step collision detection, and then possibly run a per-pixel collision check only if the Rectangle collides. Per-pixel is really not an optimal collision check, but depending on the size of your textures, it might be fine. –  Jon Jan 17 at 0:26

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.