0
votes

Okay, I have a 2d Tile Map editor I'm working on in xna c#.

In the Draw method I loop through (with a 'for' loop) my 2 dimensional array of tiles so that my map updates and draws all the tiles every frame.

My question is, how do you draw only the tiles that are seen on screen.

Also is there a better way to draw the tile map (Rather than updating every frame).

2

2 Answers

1
votes

In the platformer demo I played around with the visible tiles were calculated and then only those tiles were drawn. I believe you will have to include them in the draw method to be drawn in each time.

Here is a snippet (this only had left to right scrolling so no vertical range was calculated). This kept track of the camera position to calculate it.

Edit:: Added the second method shows how it updated camera position based on the player position stored in a player object.

    private void DrawTiles(SpriteBatch spriteBatch)
    {
        // Calculate the visible range of tiles.
        int left = (int)Math.Floor(cameraPosition / Tile.Width);
        int right = left + spriteBatch.GraphicsDevice.Viewport.Width / Tile.Width;
        right = Math.Min(right, Width - 1);
        // For each tile position
        for (int y = 0; y < Height; ++y)
        {
            for (int x = left; x <= right; ++x)
            {
                // If there is a visible tile in that position
                Texture2D texture = tiles[x, y].Texture;
                if (texture != null)
                {
                    // Draw it in screen space.
                    Vector2 position = new Vector2(x, y) * Tile.Size;
                    spriteBatch.Draw(texture, position, Color.White);
                }
            }
        }
    }`


    private void ScrollCamera(Viewport viewport)
    {
        const float ViewMargin = 0.35f;

        // Calculate the edges of the screen.
        float marginWidth = viewport.Width * ViewMargin;
        float marginLeft = cameraPosition + marginWidth;
        float marginRight = cameraPosition + viewport.Width - marginWidth;

        // Calculate how far to scroll when the player is near the edges of the screen.
        float cameraMovement = 0.0f;
        if (Player.Position.X < marginLeft)
            cameraMovement = Player.Position.X - marginLeft;
        else if (Player.Position.X > marginRight)
            cameraMovement = Player.Position.X - marginRight;

        // Update the camera position, but prevent scrolling off the ends of the level.
        float maxCameraPosition = Tile.Width * Width - viewport.Width;
        cameraPosition = MathHelper.Clamp(cameraPosition + cameraMovement, 0.0f, maxCameraPosition);
    }
0
votes
int MapSizeX = 20;   
int MapSizeY = 20;
int LeftCornerX = 0;       //the position of the Tile in the 2Darray that is going
int LeftCornerY = 0;       //to be drawn in the left corner of the screen.
int ScreenSizeX = 10;
int ScreenSizeY = 10;

public Tiles[,] tiles = new Tile[MapSizeX, MapSizeY]; //list of all Tiles

//then you can draw it like this....

int counterX = 0;  //represents the position on screen
int counterY = 0;

// y and x inside the for loops represents the position in tiles

for(int y = LeftCornerY; y < MapSizeY <  y++)
{
    for(int x = LeftCornerX; y < MapSizeX <  x++)
    {
         if(counterX  < ScreenSizeX && counterY < ScreenSizeY)
         {
              tiles[x, y].draw(tiles[counterX , counterY]);
         }
         counterX ++;
         //when you do like this you draw the tiles you want
         //at the position you want. In the draw method you just
         // drawn the tile you want at the position of the tile you 
         // send as in parameter to the draw method.
    }
    counterY++;
    counterX = 0;
}

then you just have to increase the LeftCorner variables to draw another part of the map