Sprite won't draw several times at same location

I’m using MonoGame 3.8.0.1641. I’m building a top-down dungeon crawler; nothing fancy. I have a top-down view of a dungeon corridor. At one spot, there are three doors leading in different directions on one tile. See image:

image

The problem is that the west door in the center doesn’t render. You can see on the other side of the tile; the east half of the door renders fine. And you can see west doors do normally render (e.g. the door to the far left).

I’m using the same sprite (the door sprite) in the same position and just rotating it 90° for each SpriteBatch Draw call.

If I turn off all the east doors, the west door renders fine (but then, of course, I don’t have any east doors).

I render the doors in this order:

  1. North door
  2. East door
  3. South door
  4. West door

If I change the order and render the east doors last, then they don’t show up!

The code for rendering the west door is below, but it’s similar to how they all are:

    if ((tile & (uint)con.Tile.DoorWest) > 0)
    {
	    // Weird thing I have to do because rotating the sprite moves it one block to the left
		blockRect.X += blockRect.Width;
		
		// rotate sprite and draw it
		float rotation = (float)ConvertDegreesToRadians(90.0f);
		_spriteBatch.Draw(_doorSprite, blockRect, srcRect, Color.White,
						  rotation, origin, SpriteEffects.None, 1.0);
	}

The sprite itself is pretty simple. It’s a PNG with a transparent background. It’s just a few black lines and it’s the same size as a full tile:

image

I thought the transparent part of the tile might be drawing opaque, but that can’t be the case because then the north door would get cut off as well.

I tried lots of other things, like playing with opacity, z-order and whatnot, but nothing makes any difference. I tried a different sprite which has a magenta background instead. While the magenta renders as transparent like it should, it displays the same erroneous rendering.

Any ideas?

Try passing a DepthStencilState.None to SpriteBatch.Begin,
or create one that has DepthBufferFunction = GreaterEqual / LessEqual.

Maybe those are already the defaults, I don’t remember.
It’s worth giving it a trying.

When do you render the white background? I think the west door is being rendered but overwritten by the white tile, test to render the whole thing without background and only the doors and see if you get it rendered.

1 Like

Set the origin to the center of the texture, it’s top left corner by default. I think you might be drawing it somewhere else.

Check the depths, of the draw calls - if they are all the same, they might be random. Do the Tiles first, then the doors.

Use MathHelper.ToRadians(degrees) instead of ConvertDegreesToRadians().

I think they might be doing this already… not sure though. There’s an origin in the draw call. Having said that, if your rotation is always in 90 degree increments, you could probably just flip your sprites horizontally and vertically and not have to worry about rotation at all.

I don’t think it’s a rotation issue anyway, otherwise none of the doors would work? Not sure though.

This is my guess as well. Something seems off with the ordering but it’s hard to say without more code.

Sprites are just drawn upon each other - as your white has no alpha it’s not getting mixed with whatever is in the background. The way you do it currently will just not work. Nothing to do with zbuffer, but with alpha blending.

So - you can try to fiddle around with alpha blend states or even stencil … but what I would do is separate the white background of the sprite from the actuall “door” (having the white parts transparent).

Paint all backgrounds first, Paint all doors over it afterwards - they dont need to blend, they just plot fine above each other

Thanks for all the input. To answer some questions:

  1. I do draw the “tiles” first. I draw the doors as the last step.
  2. Most of the sprite is transparent. If part of it was blocking, drawing the north door and east door wouldn’t work. One would overlap the other.
  3. Thanks for the tip on MathHelper.ToRadians(). I didn’t know about that. I’m using it now, but it gives me the same results.

I found something else that’s weird when I turned off drawing the tiles. This is the same area as in the original question, but with walls and tiles turned off:
image

See the west door rendering one tile BELOW where it should? It only happens with that one tile. All other west doors render correctly. It gave me an idea of what to try (and gives me more debugging ideas too).

Again, thanks for all the responses! I’ll post another question if I can’t lick it with my new information.

2 Likes

Is it always the last door in the list of doors that does not render?

Can you just post all the relevant code? I think we’ll catch it in no time then. (repo link?)