0
votes

I'm currently working on a XNA game prototype. I'm trying to achieve a isometric view of the game world (or is it othographic?? I'm not sure which is the right term for this projection - see pictures). The world should a tile-based world made of cubic tiles (e.g. similar to Minecraft's world), and I'm trying to render it in 2D by using sprites.

So I have a sprite sheet with the top face of the cube, the front face and the side (visible side) face. I draw the tiles using 3 separate calls to drawSprite, one for the top, one for the side, one for the front, using a source rectangle to pick the face I want to draw and a destination rectangle to set the position on the screen according to a formula to convert from 3D world coordinates to isometric (orthographic?).

(sample sprite: Sprite)

This works good as long as I draw the faces, but if I try to draw fine edges of each block (as per a tile grid) I can see that I get a random rendering pattern in which some lines are overwritten by the face itself and some are not.

Please note that for my world representation, X is left to right, Y is inside screen to outside screen, and Z is up to down.

In this example I'm working only with top face-edges. Here is what I get (picture):

alt text

I don't understand why some of the lines are shown and some are not. The rendering code I use is (note in this example I'm only drawing the topmost layers in each dimension):

/// <summary>
/// Draws the world
/// </summary>
/// <param name="spriteBatch"></param>
public void draw(SpriteBatch spriteBatch)
{
    Texture2D tex = null;

    // DRAW TILES
    for (int z = numBlocks - 1; z >= 0; z--)
    {
        for (int y = 0; y < numBlocks; y++)
        {
            for (int x = numBlocks - 1; x >=0 ; x--)
            {

                myTextures.TryGetValue(myBlockManager.getBlockAt(x, y, z), out tex);
                if (tex != null)
                {
                    // TOP FACE
                    if (z == 0)
                    {
                        drawTop(spriteBatch, x, y, z, tex);
                        drawTop(spriteBatch, x, y, z, outlineTexture);
                    }

                    // FRONT FACE
                    if(y == numBlocks -1)
                        drawFront(spriteBatch, x, y, z, tex);

                    // SIDE FACE
                    if(x == 0)
                        drawSide(spriteBatch, x, y, z, tex);

                }
            }
        }
    }
}


private void drawTop(SpriteBatch spriteBatch, int x, int y, int z, Texture2D tex)
        {
            int pX = OffsetX + (int)(x * TEXTURE_TOP_X_OFFRIGHT + y * TEXTURE_SIDE_X);
            int pY = OffsetY + (int)(y * TEXTURE_TOP_Y + z * TEXTURE_FRONT_Y);
            topDestRect.X = pX;
            topDestRect.Y = pY;
            spriteBatch.Draw(tex, topDestRect, TEXTURE_TOP_RECT, Color.White);   
        }

I tried using a different approach, creating a second 3-tiers nested for loop after the first one, so I keep the top face drawing in the first loop and the edge highlight in the second loop (I know, this is inefficient, I should also probably avoid having a method call for each tile to draw it, but I'm just trying to get it working for now).

The results are somehow better but still not working as expected, top rows are missing, see picture:

alt text

Any idea of why I'm having this problem? In the first approach it might be a sort of z-fighting, but I'm drawing sprites in a precise order so shouldn't they overwrite what's already there?

Thanks everyone

3

3 Answers

1
votes

Whoa, sorry guys I'm an idiot :) I started the batch with SpriteBatch.begin(SpriteSortMode.BackToFront) but I didn't use any z-value in the draw. I should have used SpriteSortMode.Deferred! It's now working fine. Thanks everyone!

0
votes

Try tweaking the sizes of your source and destination rectangles by 1 or 2 pixels. I have a sneaking suspicion this has something to do with the way these rectangles are handled as sort of 'outlines' of the area to be rendered and a sort of off-by-one problem. This is not expert advice, just a fellow coder's intuition.

0
votes

Looks like a sub pixel precision or scaling issue. Also try to ensure your texture/tile width/height is a power of 2 (32, 64, 128, etc.) as that could make the effect less bad as well. It's really hard to tell just from those pictures.

I don't know how/if you scale everything, but you should try to avoid rounding wherever possible (especially inside your drawTop() method). Every time you round some position/coordinate chances are good you might increase the error/random offsets. Try to use double (or better: float) coordinates instead of integer.