Sign in to follow this  
Silent Dragon

[C# - XNA] 2D Tile Drawing, rounding error?

Recommended Posts

Silent Dragon    184
Hi guys, I've recently been working on a tile engine in XNA and have a problem that I've been trying to fix for quite a while. The image below sums it up pretty much. As I scroll around, occasionally I get a gap inbetween tiles. I assume this is to do with how I draw my tiles. Basically, what it does is works out the portion of the tile that should be displayed within the cameras borders and then uses that percentage to work out the source area of the texture. It then draws the tile in relation to the cameras borders. I feel that this explanation is a bit crappy, so I've included my 'Draw' method. But I feel I should explain some of my variables, as they are strangely named as I've been faffing about with this for a while. Camera.x and Camera.y - Give the position of the top left pixel of the camera, relative to the top left of the screen. Camera.Position - Vector2 that gives the top left pixel position of the camera, relative to the top left of the map.
public void draw(SpriteBatch spriteBatch, Camera camera)
        {
            spriteBatch.Begin(SpriteBlendMode.AlphaBlend);

            int curDrawX = camera.x;
            int curDrawY = camera.y;

            for (int i = 0; i < rows.Count; i++)
            {
                // If the row is above the camera's view, then skip to the next row
                if (((i + 1) * tileHeight) < camera.Position.Y)
                    continue;

                // If the row is below of the camera's view, then don't draw it
                if ((i  * tileHeight) > (camera.Position.Y + camera.Height))
                    break;

                int curTileHeight;

                // Last row of tiles
                if(((i + 1) * tileHeight) > (camera.Position.Y + camera.Height))
                    curTileHeight = (int)((camera.Position.Y + camera.Height) - (i * tileHeight));
                else
                    curTileHeight = tileHeight;

                for (int j = 0; j < rows[i].Count; j++)
                {
                    // If the tile is to the left of the camera, skip to the next one without drawing
                    if (((j + 1) * tileWidth) < camera.Position.X)
                        continue;

                    // If the tile is out of the camera's view, then don't continue with this row
                    if ((j * tileWidth) > (camera.Position.X + camera.Width))
                        break;

                    // float curTileWidth;

                    Rectangle dest, src;
                    Texture2D texture = tiles.getTile(rows[i][j]).getTexture();
                    Color colour = new Color(new Vector4(1f, 1f, 1f, alpha));

                    double startPixelXTile = (j * tileWidth >= camera.Position.X) ? 
                         0 : 
                         (texture.Width * ((camera.Position.X - (j * tileWidth)) / tileWidth));
                    double startPixelYTile = (i * tileHeight >= camera.Position.Y) ? 
                         0 : 
                         (texture.Height * ((camera.Position.Y - (i * tileHeight)) / tileHeight));

                    double endPixelXTile = ((j + 1) * tileWidth > (camera.Position.X + camera.Width)) ? 
                         (texture.Width * (((camera.Width + camera.Position.X) - (j  * tileWidth)) / tileWidth)) : 
                         texture.Width;
                    double endPixelYTile = ((i + 1) * tileHeight > (camera.Position.Y + camera.Height)) ? 
                         (texture.Height * (((camera.Height + camera.Position.Y) - (i * tileHeight)) / tileHeight)) : 
                         texture.Height;

                    src = new Rectangle(
                        (int)Math.Round(startPixelXTile, 0),
                        (int)Math.Round(startPixelYTile, 0),
                        (int)Math.Round((endPixelXTile - startPixelXTile), 0),
                        (int)Math.Round((endPixelYTile - startPixelYTile), 0));

                    int curTileWidth = (int)Math.Round((tileWidth * ((float)src.Width / texture.Width)), 0);
                    curTileHeight = (int)Math.Round((tileHeight * ((float)src.Height / texture.Height)), 0);

                    dest = new Rectangle(curDrawX,
                        curDrawY,
                        curTileWidth,
                        curTileHeight);

                    if (camera.Debug)
                    {
                        // Print out some nice debug messages
                        System.Console.WriteLine(src.ToString());
                        System.Console.WriteLine(dest.ToString());
                    }

                    spriteBatch.Draw(texture, dest, src, colour);

                    // Update the variables
                    curDrawX += (int)Math.Round((tileWidth * ((float)src.Width / texture.Width)), 0);
                }

                // Reset the variables for the next row
                curDrawY += (int)curTileHeight;
                curDrawX = camera.x;
            }

            spriteBatch.End();
        }



Any general tips on improving the code are welcome, and anyone who helps me fix this issue gets a cookie! Thanks, - SD

Share this post


Link to post
Share on other sites
Moe    1256
Just out of curiosity, are you using tiles that are a size of a power of 2 (Eg: 32x32, or 64x4)?

Share this post


Link to post
Share on other sites
Silent Dragon    184
Ahh, I wonder if that is something to do with it. Most of them are, but I just grabbed some other images to test it, and I remember that one is 20x20. I'll try it with purely images of powers of 2 and report back.

Thanks for the feedback,
-SD

Share this post


Link to post
Share on other sites
Silent Dragon    184
Thanks Moe. I feel rather foolish now, going over and over the code, doing drawings and etc. Seems to work without any gaps now, which is nice, although id looks odd when scrolling, this could be that I've tinkered with the code too much and messed something up, or just that I'm scrolling too fast. But ahh well, I'm glad there are no more gaps.

- SD

Share this post


Link to post
Share on other sites
Moe    1256
Actually, I was wondering if your tile sizes were sizes of a power of 2, not your texture sizes. I guess it doesn't matter as your problem seems to be solved.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this