#bevy_ecs_ldtk tile access help
121 messages · Page 1 of 1 (latest)
from the dependancy bevy_ecs_tilemap, it seems that you are supposed to use this:
using bevy_inspector_egui, I found one of those components
under the Walls layer of my LDTK file
how do i get access to this though?
it felt like there should be an LDTK resource to handle stuff like this but i dont think there is
https://docs.rs/bevy_ecs_ldtk/0.10.0/bevy_ecs_ldtk/ldtk/loaded_level/struct.LoadedLevel.html#method.layer_instances this seems closer to an answer,
id rather have direct access to the walls layer or some function to get it, but even so i dont know how to get a reference to a LoadedLevel in the first place
im very lost in this long chain components with no guide
added tags to this post, forgot to previously
if i can get the world, i can get the level, which has the layers i need to access
how do i even get a reference to the world within my player movement function???
ok, i guess i could query TileStorage with a Name that equals "Walls"?
this all feels so wrong
the LDTK tutorial itself wants me to create a Wall entity, register one for every tile, cache their positions on spawn, and seemingly go through all of them to check if its at the position you want
why are we reinventing this?? its a grid of tiles we literally know where the data for (5,5) is, why not just access it directly?
this is all so confusing
would be really nice to have a higher level resource to get the tile at a certain spot. even if i do this, there could be multiple levels loaded at once and a tile could be in either one
hep
You can get access to the LDtk world through querying Handle<LdtkProject> and using the handle to get the actual asset from Asset<LdtkProjet>, after that there is a worlds() function on LdtkProject that can get you the world(s), or look at the other functions, some can give you access to level I think. I'm on my phone tho so none of this is tested, just looking at the doc.
ok, this is a start. how do i write that query exactly?
Looking a bit more into it, once you have a LDtkProject, you can do ldtk_project.as_standalone() then you can get a LoadedLevel from that
i was looking at this before but was very lost. though i did see as_standalone() requires all my maps to be in one file? this is probably fine for now at least
i guess this also would make my function unable to be parallelized, because it would claim access to the LDTK world and not allow anything else to? (not sure if thats how it works)
In your system would look like:
my_system(project_handles: Query<Handle<LdtkProject>>, assets: Res<Asset<LdtkProject>>, ...) { todo!(); }
Only if mutable, but other systems that don't need it would still run I believe
Yes, it does need to be in the same file, there is something else for External levels or whatever they call it, but I haven't looked into it
mhm, was just curious
should be fine until i end up needing that, which i hope by then ill have some more intuition on all of this
Cursory looks tells me that they are somewhat different, but shouldn't be a problem for your use case as far as I can see, you get different methods for getting the LoadedLevel, but after that it looks like the same
yeah
i had a really hard time parsing the documentation, i could tell the tree structure that existed but was completely lost on how to get access on it
querying ldtkproject, but its a struct, i thought you queried entities?
anyways im very appreciative, ive been stumped on this for a while and this seems like the thing i needed!
We are querying the Handle for it, and handles are components, the actual asset is a Resource. You can query for components (which are structs or enums) and the entity id.
The way I see it, is that the query is a big filter over what kind of components the entity you are querying must have. Entities are just a bunch of components hiding in a trench coat with a serial number slapped on it. You can even see the Entity as a component that tags the group of components it's in as a particular entity, but that's not super correct and only in the point of view of a Query (i.e Query<(Entity, &MyComponent)> looks to me like we want an Entity component and a MyCompoment that are associated)
But anything you see in inspector_egui that's not an actual value is a component, even Children is a component
so ldtkproject is a component, that belongs to a resource?
i thought you could just require resources a different way
No, LdtkProject is an Asset, which you access with Res<Assets<LdtkProject>>, the Handle for the project is a component however.
uhhhh
god im very new to this, but also I have to learn by doing something? especially since theres no like official tutorials. at least not past the basics.
let me double check some of these terms
i misread your original code snippet, there are two <LdtkProject> s, not sure why yet
Taking the example from earlier:
project_handles: Query<Handle<LdtkProject>>,
assets: Res<Assets<LdtkProject>>, ...)
{
// Get the handle from the entity
for project_handle in &project_handles {
// Get the actual asset from the handle
let project_asset = assets.get(project_handle);
}
}
LdtkProjectis anAsset
oh so like how my character sprite is an asset? you mean this is like the reference to the actual file
Most of the time an Asset is the data resulting from loading in a file, yes
ok, right. asset is kind of a term used for a lot of things so i wasnt connecting that right away
there wouldnt be more than one project_handle and project_asset unless i was loading two files at once right?
then when you add it to the other assets, you get a Handle back, which is an id to be able to get back to that asset
maybe i could do the like, enforce that theres only one of them, query thing
correct
I you load only one I don't think it matters, but I'm not a software engineer
hmm i should learn what exactly the <> signifies in rust
and what res<> is
the others seem to make sense
oh actually the code is throwing errors anyways
Res and ResMut are to get Resources, the later for mutable ones
<> is for qualifying generics in rust
yours or mine? Mine was just an example, haven't tested it
adding your code to my code
What's it complaining about?
the trait
QueryDatais not implemented forbevy::prelude::Handle<bevy_ecs_ldtk::assets::LdtkProject>
Oh, interesting, I guess it's just to hold the handle that it's there then, odd.
but if you only have one, you can just iterate over the Res<Asssets<LdtkProject>>
so i could use the, throw error if there is more than one, instead of iterating?
i remember that kinda structure being somewhere in what exists of the bevy tutorials
im gonna find it
No, like you pointed out we can't query the handle, so you can just
fn my_system(projects: Res<Assets<LdtkProject>>) {
for project in projects.iter() {
/* whatever you need */
}
}
you'll need to handle it if you load multiple projects later on
But I do agree with you, this seems waaayyy convoluted just to get to a tile
i mean, the way the tutorial suggested, just seemed
weird
here we have a clearly defined spatially structured file, so it'd be possible to point to the data just from the coordinate (ehh unless you have overlapping tiles? maybe this isnt always true)
even if not, an entity is created for every tile, and for every int grid
and then it asks you to go and make new ones and cache their positions into a list and then search the list by coordinate
i have never ever seen anything like that
its like if you exported your level to json and string searched for the tile coordinates?
this way is also convoluted, but I know the underlying bevy_ecs_tilemap has functionality to get() tile by coordinate which seems like the reasonable thing that i actually want
but now i have to possibly deal with multiple project files, multiple loaded levels, all just to access a tile
at the very least it seems like something i should move to its own function or service or whatever, but im not sure how i'd do that
Why are you trying to access this specific tile?
for any purpose?
right now specifically, im trying to port a physics system ive made before
lets say a simplified version is, you cant walk into a space if theres a tile there
but also just for any purpose, i can assume i will need to check tiles at coordinates and get information about them, in general
and the suggested approach, of create a structure for each purpose, and cache their positions, then search the list seems so weird
i really really want a get_tile_at_coordinate(), and all its related information, because i imagine this is the kind of thing id be using all of the time
i tried to downgrade to the dependancy itself, bevy_ecs_tilemap, because maybe i'd have finer control over things? but i couldnt even get the example to work
instead of like
spikes.contains(coords)
walls.contains(coords)
doors.contains(coords)
which seems convoluded
im imagining something more like tile = tiles.at_coords(coords)
and then having all the relevant information?
LDtk (the program itself) allows you to tag tiles with an enum (for collision tagging, etc), so I would imagine that you should be able to access that pretty easily with bevy_ecs_ldtk
just.... it may be my stubborness because maybe i could just move on with this but... really, list.contains
seems so wrong
i would think so too but i dont know how
thats what im trying to figure out i guess
i thought this would be a good place to start, if i had sprites and a tilemap id be able to get pretty far and build some intuition and learn
who knew just the tilemap part would be so tedious
Looking at the doc, I don't see any way to get to those values on the tiles. I think the person that made bevy_ecs_ldtk was expecting people to use entities for carrying data. And the only way I found to access tile data, was through what we've been talking about, getting to the LoadedLevel, Level, LayerInstance, and TileInstance, which is a flat array that you would have to filter.
entity based tiles just seems so wrong to me, and, ineffecient? queries, searches, get slower with count right? an index does not
what do i even do. should i fold and do it in a weird uncomfortable convoluded way
or give up or maybe theres a third option
With what you have right now, I would query for Name and TileStorage, and check the name. Otherwise, I would use a IntGrid/Entity to carry the data, and leave the sprite on the TileMap, so you still get the benefits for rendering. Having extra entities isn't a big deal, especially if they are not rendered.
The only down side is that stuff is split in LDtk, and you have to remember to put both on your map
wdym by this?
If you go for the IntGrid/Entity to carry the data, and the sprite on the TileMap, they won't be connected, like they would if you had the sprite on the Entity directly, so you would have to put both of them on the map each time
But it might be smarter to test and see if using Entities with a sprite has a significant impact on render time or not
the tiles are already entities attached with sprites right?
i could just.... make my own tile renderer that only does what i need it to do...
i hate how my mind goes to this place because it could be a good solution but it also very likely could be outside of my skills
Yes, so having a ldtk entities instead of tiles shouldn't be a problem