[Solved] Frame-rate drops when drawing 2D map tiles.

Update: I figured out it has nothing to do with the camera but instead framerate drops when drawing my map tiles onto the screen.

I’ve came across an incredibly strange bug when trying to move my game’s camera over the update loop which I’ve been struggling to pinpoint the exact cause.

As the camera moves, all the “objects” in view appear as if they’re trying to catch up with the camera or as if they’re “shaking”.

Here’s a link to a video showcasing the bug in action (For further reference): https://streamable.com/m4zuf3

Any and all guidance is appreciated, thanks.

Hi!

This looks like one of those cases that crop up when things are getting auto-cast to int and you lose some precision. Maybe make sure you’re not using integers anywhere except where you actually pass the values out to your draw calls.

One thing that jumps out from the code in your video is…

C.Position = new Vector2(C.Position.X + 1 * 60 * dt, C.Position.Y);

Try the following…

C.Position = new Vector2(C.Position.X + 1f * 60f * dt, C.Position.Y);

I can’t be certain, and I can’t see the rest of your code, but that’s the first thing that jumps out at me :slight_smile:

1 Like

Actually it has nothing to do with the camera

I just noticed this:

Capture

There are these split framerate drops whenever I add this line:

m_mainLevel.Draw(spriteBatch);

Draw Function:

public void Draw(SpriteBatch sb)
        {
            //Draw Background
            for (var i = 0; i < BackgroundTiles.Length; i++)
            {
                int id = BackgroundTiles[i].m_id;

                int column = id % TilesetTilesWide;
                int row = (int)Math.Floor((double)id / (double)TilesetTilesWide);

                int width = Map.TileWidth * 2;
                int height = Map.TileWidth * 2;

                float x = (i % Map.Width) * width;
                float y = (float)Math.Floor(i / (double)Map.Width) * height;

                Rectangle tilesetRec = new Rectangle(TileWidth * column, TileHeight * row, TileWidth, TileHeight);
                Rectangle dest = new Rectangle((int)x, (int)y, width, height);
                sb.Draw(Tileset, dest, tilesetRec, Color.White);
            }
        }

Is the problem that I’m drawing too many tiles per frame? the map size is 250 x 250 tiles, with each tile being 16x16px.

Solved!

With just one line of code:

if(bounds.Intersects(dest)) sb.Draw(Tileset, dest, tilesetRec, Color.White);

1 Like

Ah, yes, it definitely helps to limit the number of things drawn to only what can be drawn on the screen. I’m glad you figured it out, nice! :smiley:

If what you have is working, definitely keep moving forward!

For the sake of conversation though, consider that you can further optimize your tile drawing. Currently you’re looping through the entire set of background tiles, then checking to see if it’s on the screen before you draw it. I’m not sure how your tileset data is arranged, but you might consider having it arranged in a logical order, with reference to the screen, inside your background tiles array. Then, you can cheat and only draw what’s on the screen from the array directly.

Consider the case where your tiles are arranged in a two dimensional array where each array index is an x and y tile position. You can calculate the starting tile indices, as well as how many tiles are on the screen in both the x and y directions. Now your for loop can iterate over only the tiles that are being shown on the screen.

Like I said, if what you have is working, roll with it! No need to optimize something that doesn’t need to be optimized. Just something to keep in the back of your mind though in case you find you need it down the road.

Happy coding!