Search code examples
c#xna-4.0

Most efficient way to select a number of classes from a large list of classes?


Basically I'm attempting to make a tile engine in XNA 2D and I'm currently using a big list of Tiles (my class holding all data for a tile) and selecting those in range of my view, then displaying them on the screen.

The problem I have is, obviously, the larger my overall list of Tiles becomes the more lag I experience when attempting to pick out the Tiles in range. I'm currently using Linq inside a for loop to select the tiles, like so:

//loop from the maximum view at the top of the screen to the maximum view at the bottom
for (int height = topView; height < bottomView; height++)
{
    //loop from the maximum view to the left of the screen to the maximum view of the right
    for (int width = leftView; width < rightView; width++)
    {
        //select the tile at this grid position
        Tile t = tileList.Where(x => x.GridPosition == new Vector2(width, height)).FirstOrDefault();
        if (t != null)
        {
            //calculate the screen position and add it to the list of local tiles within range
            t.ScreenPosition = new Vector2(screenWidth * 30, screenHeight * 30);
            localList.Add(t);
        }
        else
        {
            //the tile wasn't found, add a random blank one to fill the gap.
            Tile brokenTile = new Tile(game, new Vector2(width, height), 9001);
            brokenTile.ScreenPosition = new Vector2(screenWidth * 30, screenHeight * 30);
            localList.Add(brokenTile);
        }
        //increment the screen width used to calculate the screen position
        screenWidth++;
    }
    //increment the screen height used to calculate the screen position and reset the width
    screenHeight++;
    screenWidth = 1;
}

I'm wondering if there's a way to do this more efficiently, ideally to reduce the lag experienced when increasing the overall size of the 'map' and selecting those tiles in range.

The only thing I can think of is some way to split the total list into 'chunks' when the map is loaded, and only looking in each chunk to pull out Tiles.. however I'm not quite sure how I'd do that because it might be a hassle if I need to pull nodes from multiple 'chunks' Any help on a good way to do that would be great too though!

Thanks alot! :)

Edit: here's some screenshots: https://i.sstatic.net/DYyFx.png compared to https://i.sstatic.net/uRoMY.png


Solution

  • I'd consider using some form of space partitioning, such as a quadtree.

    This would mean assigning your objects to regularly-sized quads based on their position. You'd be able to efficiently determine what quads are visible, and each quad would know what objects it contains (although you'd need to manage this as objects moved).