• Advertisement
Sign in to follow this  

45° Tilemap depth draw order.

This topic is 777 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have created some tilted topdown tilemaps in the past and I'm wondering about other and preferably better ways to tackle depth sorting or z buffering when walls and taller objects come into play and the player is able to move smoothly between tiles. When all things are static there is no problem when you draw from top to bottom but once the player starts to move on the grid in the direction of draw order things need to be fixed.

 

The easiest solution is to just draw the floor first. Then loop again to draw all taller objects but in consideration of the movable entities Y position. But this requires a double loop where 50% of the iterations won't draw anything. It also needs to check all entities every time the double loop goes a y level down. I rather draw in a single loop but this requires me to use some hacky solutions to redraw walls.

 

For example, when I draw from left to right and move a sprite to the right it will show up below the right tile (until the entity shifts in X coordinate). I could keep track of where the entity is moving to and from so I could draw it on the last tile in the order (which already feels a bit hacky). But doing this for the Y direction will cause problems when encountering walls and moving diagonally alongside them. Now I also have to check if there might be a wall that should block me and redraw that wall, and while this works it feels really hacky. When a wall needs to be redrawn all objects below it that are higher then 1 tile need to be redrawn.

 

I usually have my movable entities in a 2d array, this makes them easy to look up on a specific tile and I don't have to loop trough some sort of list each time I draw a tile to see if there is a entity in it. However doing it the way I described above made me create another hacky way. I put my entities in a sorted list on Y position and just loop this once after the map is been drawn and redraw all walls that might need redrawing.

 

I keep running into these issues and while I can fix everything with some hacky if statements and redraws I'm really looking for a one size fits all solution that I cannot think of and neither find anywhere.

Share this post


Link to post
Share on other sites
Advertisement

If you're using a depth buffer then you should be able to solve this with the normal 30° perspective method, which is to make z equal to (y + (layer * layer_depth)) for all sprites/tiles. I don't think I completely understand what you're saying though.

 

With regard to what looks like a concern about "a double loop where 50% of the iterations won't draw anything", don't worry about it. Unless you're doing something really crazy it shouldn't harm performance enough to care about, even a little bit. Most tile-based drawing setups use several layers, most of which are very sparsely populated. Iterating the tilemap is very quick and easy for the CPU (again, assuming no crazy) and no work is generated for the GPU.

Share this post


Link to post
Share on other sites

Unless your floors are terribly complex, double iteration is fine. I actually worked on a game once where graphics were slanted such that they could cover the tile at (-1, 0) from them, and so had to draw each tile at each draw order in a different pass, plus a pass to "smooth" animation of moving players and monsters between tiles. The game had 5 draw orders, so that was 6 iterations.

If you really want to speed up that second pass, you could store all tall objects in a separate list for the second pass, or you could create a new type of linked list, in which there are two links on each node. The first link will be ALL objects (the whole list), while the second link will only contain nodes for tall objects.

Share this post


Link to post
Share on other sites

When all things are static there is no problem ... The easiest solution is to just draw the floor first. Then loop again to draw all taller objects but in consideration of the movable entities Y position.


Nope.

Painter's algorithm applies to this type of scene. Draw it back to front, bottom to top.
 
If you're looking out across an isometric scene, draw the most distant row, bottom to top.  Then the next closer row, bottom to top. Then the next closer row, bottom to top.
 
 
 
Hopefully you're also rendering in a way that won't saturate your bus.  Modern graphics architecture doesn't like the tile pattern.
 
Note that when this style was popular the graphics hardware for games was generally built around tile-based rendering.  Console of the era operated on tiles, you loaded up your tiles and then passed arrays of index/location pairs.  Since you are working on today's hardware, optimized around a low number of mesh rendering calls, you will want to figure out good ways to cache and batch your scene to minimize draw calls.

Share this post


Link to post
Share on other sites

Painter's algorithm applies to this type of scene.

 
Forum software ate your link; here's the correct one.

[Edit:] ??? Forum software ate my link also. =(...

Fixed it. Fixed it, bah, it's really not liking that apostrophe in the URL. dry.png

 

But just incase, here's the plaintext URL: 

https://en.wikipedia.org/wiki/Painter's_algorithm
Edited by Servant of the Lord

Share this post


Link to post
Share on other sites

Painter's algorithm applies to this type of scene. Draw it back to front, bottom to top.

 

Yeah obviously, like I said I have drawn my fair share of tile maps, and massive multi layered isometric maps with 90 degree rotation without problems. I just find my solutions a bit hacky. I don't think multiple passes are really necessary since all I have is a static environment with slightly taller walls that cover the the moving entities when behind. Maybe putting the entities in a set and ordering them by Y position can get me some results.

 

 

 


Unless your floors are terribly complex, double iteration is fine. I actually worked on a game once where graphics were slanted such that they could cover the tile at (-1, 0) from them, and so had to draw each tile at each draw order in a different pass, plus a pass to "smooth" animation of moving players and monsters between tiles. The game had 5 draw orders, so that was 6 iterations.

 

Pretty complex for a none isometric view I guess, I have about 50 types/shapes of "ceiling" tiles to top of the walls and some show through whats behind them. My maps are randomly generated and all these tiles are lining up. I will introduce pits as well and that adds another 50 tiles. But everything takes place on 1 "height". It just feels so hacky to redraw when a movable character passes them behind in diagonal way but it surely must be a lot more efficient then running another loop for the walls (never actually tested that... shame on me).

 

I'm going to have another go at this tomorrow and otherwise I just use redraws or a double pass.

Edited by menyo

Share this post


Link to post
Share on other sites


Modern graphics architecture doesn't like the tile pattern

 

It does if you use a single spritesheet instead of a million tiny images. (I don't understand why people do that.)

Share this post


Link to post
Share on other sites


Hopefully you're also rendering in a way that won't saturate your bus. Modern graphics architecture doesn't like the tile pattern.

It's entirely possible that he's software rendering. Or is this just not a thing people do anymore?

Also...

 

 


Modern graphics architecture doesn't like the tile pattern

 

It does if you use a single spritesheet instead of a million tiny images. (I don't understand why people do that.)

 

this. (they do it because it's easier at the very first stages of development, and it doesn't become a performance issue until fairly late in development, at which point refactoring might be too complicated. This is one of those special cases where one should optimize early...)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement