Open svenallers opened 2 years ago
I just dug into the calculation of the position of the tiles in the tilesets and it seems that LDtk is handling indices differently, thanbevy_ecs_tilemap
when the size of the sprite sheet does not align perfectly with the tile size and their spacing (meaning the width is not n * (tile_size + spacing) - spacing
but sth. different).
Seems that LDtk adds an index for the "not complete" tile. See:
Which implies that one would need to ceil when calculating the number of columns based on the sheet size, but bevy_ecs_tilemap
floors the result. See https://github.com/StarArawn/bevy_ecs_tilemap/blob/9e431db7aad111a0fadeff4aff92524439912a57/src/render/shaders/tilemap.wgsl#L55:
var columns: u32 = u32((tilemap_data.texture_size.x + tilemap_data.spacing.x) / (tilemap_data.tile_size.x + tilemap_data.spacing.x));
That explains why the shown tiles were off by 9 (the grass tile intended was in the 10th row (row index = 9) and with having one column less in each row you always have an offset that is the row index).
I did use a sprite sheet that was from an external source, thus I was not aware that it is not perfectly aligned when the space is included. After I adopted the sheet everything was fine. (The width was 32 * 128px = 4096px
before, which did not take the spacing of 2px
into account (4096px / 130px ~ 31,5
). After increasing the width to 32 * 130px - 2 = 4158px
everything was fine)
But still, I think it could make sense to translate the LDtk indices to fit the bevy_ecs_tilemap
calculation in those cases, to not step into the trap that easily.
Thanks for the issue, and also thanks for looking into it. Tile spacing has been a bit touchy from the beginning, and this explanation makes a lot of sense.
The upcoming release for bevy_ecs_tilemap will have a new API, and it might allow providing custom TextureAtlas
s to its maps. So, I'm hoping that we'll be able to more easily replicate LDtk's indexing techniques when that time comes. If not, we can also go back to using the LDtk-provided "src rect" for the tiles instead of the LDtk-provided atlas indices.
For now, the best workaround is, as you mentioned, adapting the sheet itself. Sorry about that.
Yes, I was already thinking about solving it by either recalculating indices and using the translated ones for the bevy_ecs_tilemap::tile::Tile
or by faking a bigger sheet by using a calculated size for bevy_ecs_tilemap::LayerSettings.texture_size
instead of the actual size, which then would be columns * (tile_size + spacing) - spacing
. But both feel suboptimal, as the first does not properly emulate the behavior of LDtk and the second one is basically faking wrong data to work around the issue. And both would probably decrease maintainability as they would make the code harder to understand, plus the first solution would probably make it even very hard to debug as one would be wondering why the indices are different, as long as one is not aware of the circumstances.
Having a custom TextureAtlas
sounds way more elegant. Hope that works out.
Hi, I currently have the issue that the rendered tilemap does not look at all like the one I created.
Here is how it looks in LDtk:
And here is how it is rendered when starting my game:
The tileset is using a spacing of 2px and therefore I enabled the atlas feature. My code currently looks like this:
main.rs
cargo.toml
A link to the full codebase, having the issue including the ldtk file and resources: https://github.com/svenallers/bevy-racer/commit/1e7e76d63d7247ea3a73b31679bfa75717afdd16
Could also be that the issue is on me, but I have no clue how to solve it.