How can I set the origin for tiles in a tileset (for YSort)?

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

I’m trying to use YSort with a player and some objects created from tiles in a tilemap.
The objects are constructed from individual tiles deliberately, and I’d like to keep this set up if possible.

I’ve uploaded a simple example project here. The arrow keys move the player.

I have a wardrobe that is 3 tiles high. It doesn’t completely occupy 3 tiles, and is slightly set back within the bottom tile to make it appear as though it is pressed against a wall. I’ve drawn a blue line at the bottom of the tile to show where it is. The player is of a similar height, and I’ve drawn a red line to represent the player’s feet.

The origin of the player is at its feet, and the tilemap is set to have its origin in the bottom left.

YSort compares the bottom of the tile (i.e. the blue line) against the bottom of the player (i.e. the red line), leading to situations like this:

The player renders behind the wardrobe

What I want is to set the Y coordinate that the tile uses for YSort to the bottom of the wardrobe, but I can’t work out how to do it. Is it possible?

I’ve seen lots of people talking about using the Tex Offset property to fix situations like these, but I don’t understand how that would apply in this case. Changing the Tex Offset moves the wardrobe sprites down (and away from the wall), and defeats the point of offsetting them within the tileset image in the first place.

Just wondering, why do you want to have the origin on the bottom left?

exuin | 2020-10-02 04:19

Based on tutorials and other posts I’ve read about YSort, it seems to be the easiest way to reason about things. The player’s location is represented by the character’s feet, so it’s logical that the position of other objects is represent by the lowest point as well. Of the three origin options that TileMap provides, “Bottom Left” is the closest.

I was hoping I could offset the origin to fine-tune the behavior of specific tiles, but maybe it’s not possible.

Pennycook | 2020-10-02 05:02

It’s just that if you set the player as a child of the tilemap node and set the y-sort of the tilemap node to top left, it works, since the player character’s feet is lower than the top left of the tiles.

exuin | 2020-10-02 05:09

:bust_in_silhouette: Reply From: exuin

I think I understand now. What the YSort node does is draw the lower nodes on top of the higher nodes based on their y-position. In the example image you showed, the player’s feet is higher than the bottom of the tile, so the player is drawn below the bottom tile. YSort is working as intended here. You should set the origin of the tilemap tiles to the top left so that the player’s origin is lower than the tiles and so the player doesn’t display on top of the bottom tiles.

Thanks for helping with this. Your explanation of the issue is spot-on, and I agree that YSort is working as intended here.

But if I set the origin of the tilemap to the top left, the issue happens in reverse; the player is drawn above the top two tiles of the wardrobe whenever the player’s feet are below the top of the tile.

I think the only way to solve this is to have some control over the origin used by each tile individually. The origin for the bottom tile could be the top left or the “real” bottom of the wardrobe, and the origin for the top two tiles needs to be set somehow to match the origin of the bottom of the wardrobe.

Pennycook | 2020-10-02 13:48

You could just make the whole wardrobe one giant tile, but that wouldn’t allow you to make wardrobes of different sizes. My “bad” solution for stuff like this was to just make two tilesets, one that was above the player, and one that was below the player.

exuin | 2020-10-02 17:24

Yeah, I think I’m going to have to end up doing something like that (or try and modify the implementation of TileMap). It’s unfortunate that this is so tricky… I wanted the artist working on my game to be able to focus on making the maps look right without having to think about how YSort works.

Anyway, thanks for all the help!

Pennycook | 2020-10-03 20:51

:bust_in_silhouette: Reply From: alexiwto

Maybe I’m a bit late but I encountered the same problem earlier and managed to solve it. It’s quite simple when you realize. You just have to make the tilemap tile origin top left, and in the tileset, set the tex offset in negative the size of your tile (in my case was 16) multiplied by the tiles of your texture -1.

For example if your texture is 48px tall with a tilemap of 16px, you want to set the tilemap tile origin top left and apply the tex offset to Y = -32 in the tileset.

I’m not sure I follow – would you mind sharing an example? I can’t work out if what you’re saying would have to apply to the entire tileset, or if you could set the tex offset for individual tiles.

Pennycook | 2021-05-07 23:37

Inside the tileset, I assume that the individual tiles that don’t match the width and height of the tilemap are going to be individual tiles. In the individual tile is where you apply the text offset.

alexiwto | 2021-05-10 12:35