How to implement correct layer drawing of sprites in an isometric, grid-based 2D game?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ArgonCat

#The Problem#
Hi there!
I’m trying to create an isometric game, where the character can move up and down several layers of isometric tiles.
Right now I’m using several tilemaps to represent this:

This works fine when all the “tiles” are only one layer tall, but if I want to add a sprite that’s taller than one layer, like the player character, it stops working:

As is shown in the gif, by making the two-block high sprite a child of the Tilemap layer it’s on, and enabling Ysort for that Tilemap, I can get the two-block sprite to be drawn correctly for that layer. But, for layers above it, the sprite is drawn behind all of the tiles on the above layer.
#Intended Behaviour#
After some thinking, I’ve worked out the order I want sprites to be drawn in:

Or, in words:

With: x(Heading Southwest), y(Heading Southeast), and z(Upwards) being the Integer coordinates from the isometric perspective, and
screenY being the y position in godot's 2D space

1. Go to the z column with the highest screenY
2. draw all the sprites in that column, from lowest to highest
3. go to the z column with the next lowest screenY
4. draw all the sprites in that column

etc, etc…
This (hopefully) draws all sprites in the correct order
##So, my questions are:##

  1. Is there a way to get this behavior using Tilemaps and Ysort nodes?
  2. If not, what is the best way to implement this in a performant way (do I set the z-index property on 2D nodes with a script? Is that too inefficient to be run every frame?)

If there are any problems with how I’ve written this question, please tell me… I’ve never used a Q&A board before :slight_smile:
Many thanks for your help,
ArgonCat

:bust_in_silhouette: Reply From: love_this_name

To Question 1:

I think the reason the tilemaps aren’t rendering nicely how you’d like is that the y-sort origin of each tile isn’t at the bottom of the tile, but constrained to the top face. That’s a limitation of Godot 3’s tilesets, as far as I know.

stuff

I experimented with TileMaps myself in Godot 3.44. This is an axonometric one where each tile image is taller than the grid cell it occupies. Because the tiles are y-sorted this layer looks fine. Importantly, the tiles go ‘downwards’ from their cells. You can’t make a tileset where the tiles ‘emerge’ up from the grid cells.

If each tile were a hand-placed sprite, I’d make sure the origin used for y-sorting was at the bottom of the sprite, like in the 2 block tall sprite you show in your gif. The TileMap can’t do this though. Even if you set the y-sort origin property for the TileMap to bottom left, it will be the bottom left of the grid cell, not the tile image, and so it won’t y-sort properly.

In Godot 4 this issue would be very easy to solve, as in the tileset editor you can set the Y-Sort point for each tile (even below the image, which is what you’d want for tile layers above the ground).

That said, you’re using Godot 3.5, not 3.44. The TileMap > Cell > Custom Transform property does nothing for me, but if it works for Godot 3.5 it could be used to offset the tiles so they ‘emerge’ from the grid, thus fixing the problem. I am just speculating — the documentation isn’t that helpful and I haven’t tried Godot 3.5.


To Question 2:

That sounds like a really tricky thing to implement. I don’t think you can manipulate tiles in a TileMap like sprites, so you’d have to write your own custom tilemapping tool :expressionless:

Godot 3’s TileMap system sucks a lot. Godot 4’s is wayyyy more flexible, so I’d recommend switching if you can. One of my favourite features is that you can make each unique tile have custom data, so you could sample the tile below a player to check what footstep sound should play etc.

Thanks so much for this answer
I switched to godot 4, and the Y origin offset option there fixed my issues, and allowed me to implement the intended behaviour :slight_smile:

ArgonCat | 2022-10-16 15:13