Level Selection
Once you have spawned an LdtkWorldBundle
with a handle pointing to your LDtk project file, the levels you have selected will spawn as children of the world bundle.
You have a couple options for selecting levels, which will be discussed in this chapter.
LevelSelection
resource
The highest-level option for selecting a level to spawn is using the LevelSelection
resource.
This resource allows you to specify a particular level either by its indices in the project/world, its identifier, its iid, or its uid.
Once this resource is added or changed, levels will be spawned/despawned in order to match your selection.
One additional feature worth pointing out is loading level neighbors.
You can enable this with the settings resource LdtkSettings
:
use bevy::prelude::*; use bevy_ecs_ldtk::prelude::*; fn main() { App::new() // other App builders .insert_resource(LevelSelection::index(0)) .insert_resource(LdtkSettings { level_spawn_behavior: LevelSpawnBehavior::UseWorldTranslation { load_level_neighbors: true }, ..default() }) .run(); }
With this set, the plugin will spawn the currently-selected level's neighbors in addition to the currently-selected level.
This can be especially useful for GridVania/Free-style worlds where it's important to have a level spawned before the player traverses to it.
Note: this only works if you are using the LevelSelection
resource.
LevelSet
component
One component in the LdtkWorldBundle
is LevelSet
.
This component can be used for lower-level level selection.
Instead of selecting one level globally with a LevelSelection
resource, you can select a specific set of levels by their iids.
From the level_set
cargo example:
use bevy::prelude::*; use bevy_ecs_ldtk::prelude::*; const LEVEL_IIDS: [&str; 8] = [ "a3591db0-66b0-11ec-9cd7-43878cf4d0ab", "a35944c0-66b0-11ec-9cd7-6b4e2322a69e", "a35992e0-66b0-11ec-9cd7-8b2ebd1b98e2", "a359b9f0-66b0-11ec-9cd7-25dfb937d033", "a35a2f20-66b0-11ec-9cd7-db6f994e2834", "a35aa451-66b0-11ec-9cd7-438de356526d", "a35acb61-66b0-11ec-9cd7-f76e35cfda30", "a35b8eb0-66b0-11ec-9cd7-3d16ec48af10", ]; fn setup(mut commands: Commands, asset_server: Res<AssetServer>) { commands.spawn(Camera2dBundle::default()); let level_set = LevelSet::from_iids(LEVEL_IIDS); commands.spawn(LdtkWorldBundle { ldtk_handle: asset_server.load("WorldMap_Free_layout.ldtk"), level_set, transform: Transform::from_xyz(-256., -144., 0.), ..Default::default() }); } fn main() {}
This component is actually used by LevelSelection
under the hood.
So, in order for this workflow to work properly, no LevelSelection
resource can exist in the world.
This also implies, as mentioned in the previous section, that load_level_neighbors
cannot be used with the LevelSet
workflow.
However, the LevelSpawnBehavior::UseWorldTranslation
option in general does work, and should be used if you plan to spawn multiple levels anyway.
LevelSet
is ideal for more complex level-spawning needs.
It is an option if you need any level-spawning behavior that LevelSelection
/load_level_neighbors
are not capable of.
Furthermore, if you have more than one LdtkWorldBundle
spawned, it can be used to select different levels per-world, which is impossible with global level selection.
When the set of levels in the LevelSet
is updated, an extra layer of change-detection is employed to make these changes idempotent/declarative.
In other words, the plugin will observe what levels are already spawned before trying to respond to the changes in LevelSet
.
Only levels in the level set that aren't currently spawned will be spawned - and only levels not in the level set that are currently spawned will be despawned.
Everything else will be left alone, remaining spawned or despawned appropriately.