Code Monkey home page Code Monkey logo

bevy_ecs_ldtk's Introduction

bevy_ecs_ldtk

crates.io docs.rs crates.io MIT/Apache 2.0 Bevy tracking CI

bevy_ecs_ldtk is an ECS-friendly LDtk plugin for Bevy. It allows you to use LDtk projects as an asset, spawn levels, and insert bevy components/bundles on LDtk entities/tiles. This plugin is ECS-friendly, partly for its internal usage of ECS that provides extra functionality to users, and partly for its usage of bevy_ecs_tilemap for rendering tilemaps. This is all behind an ergonomic API, providing low-boilerplate solutions to common use cases. For less common use cases, strategies that leverage this plugin's ECS constructs are also available.

platformer-example

cargo run --example platformer --release

Features

  • Support for all layer types
  • Support for loading external levels
  • Hot reloading
  • Solutions for easily loading/unloading levels, changing levels, loading level neighbors...
  • Low-boilerplate solutions for spawning bundles for LDtk Entities and IntGrid tiles using derive macros (other options available)
  • serde types for LDtk based off LDtk's QuickType loader, but with several QoL improvements
  • Support for Wasm (and tile spacing) through "atlas" feature

Documentation

Documentation for this plugin is available in two main places.

In the book, the following chapters are good jumping-off points for beginners:

Cargo examples are also available in this repository:

$ cargo run --example example-name

Compatibility

bevy bevy_ecs_tilemap LDtk bevy_ecs_ldtk
0.13 main 1.5.3 main
0.12 0.12 1.5.3 0.9
0.11 0.11 1.3.3 0.8
0.10 0.10 1.1 0.7
0.10 0.10 1.1 0.6
0.9 0.9 1.1 0.5
0.8 0.7 1.1 0.4
0.7 0.6 1.1 0.3
0.6 0.5 0.9 0.2
0.6 0.5 0.9 0.1

Asset Credits

bevy_ecs_ldtk's People

Contributors

adtennant avatar bardt avatar cashwasabi avatar christopherbiscardi avatar elenakrittik avatar focustense avatar geieredgar avatar github-actions[bot] avatar hellzbellz123 avatar ispringle avatar janos-r avatar jgayfer avatar johanhelsing avatar john-toohey avatar jrasanen avatar marcoseiza avatar mscottmcbee avatar neocturne avatar nfagerlund avatar phaestusfox avatar piturnah avatar theshortcut avatar trouv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bevy_ecs_ldtk's Issues

Derive macros for int grid cell spawning

Similar to #[derive(LdtkEntity)] we should have a #[derive(LdtkIntCell)] or #[derive(LdtkIntGridCell)] that is register-able via a new App::register_ldtk_int_cell or something similar.

This shouldn't need as much access to the world as LdtkEntity does (or maybe no access at all will do), so this won't have as many attributes. Still, it should probably at least have:

  • #[int_grid_cell] for inserting the IntGridCell component
  • #[ldtk_int_cell] for having nested LdtkIntCells
  • #[from_int_grid_cell] for using From<IntGridCell>

First Release Examples

At the very least, have an example using LdtkEntity/LdtkIntGridCell traits, an example using the derives for these traits, and an example fleshing out entities from systems.

In addition, it would be nice to have at least one example with some actual mechanics.

Consider using LDtk's sample files, if their licenses are permissive enough.

Hot reloading for external levels

Hot reloading for external levels is pretty close, but when you save a level in the LDtk editor, bevy gives this warning without any AssetEvent being fired:

WARN bevy_asset::asset_server: encountered an error while reading an asset: path not found: /home/trouv/projects/bevy_ecs_ldtk/assets/levels/0000-Level_0.ldtkl
WARN bevy_asset::asset_server: encountered an error while reading an asset: path not found: /home/trouv/projects/bevy_ecs_ldtk/assets/levels/0001-Level_1.ldtkl

This is the correct path for the file and it does still exist after save.
The only thing I can think of is that maybe the way LDtk saves these level files is that it deletes the file first then writes to it a millisecond later, and bevy hot-reloading doesn't like that.
However, I looked into the LDtk source code and it looks like it's just using Node.js's writeFileSync() function, but maybe I'm missing something.

I saw in notify::poll::PollWatcher (which bevy seems to use for hot-reloading on linux) that you can set a delay for polling the filesystem, which may resolve the issue most of the time if I set it to like 50 ms or something.
I don't think that particular value is controllable from the bevy api though.
Maybe bevy should still be capable of writing AssetEvents in this scenario in the future?
This is probably upstream issue.

Tile Data example

Write an example using the TileMetadata and TileEnumTags components

Make GridCoords a newtype for IVec2?

I was just wondering about whether it might be better to wrap IVec2 instead.

#[derive(Component, From, Deref, ...)]
pub struct GridCoords(pub IVec2);

Might save some of the re-implementation of arithmetic operators and make it easier to make use of IVec2's helper methods without doing IVec2::from or .into() all the time.

LDtk 1.0 checklist

The ldtk-1.0 branch is being developed to support the first major release of LDtk. This issue is intended to track new features that may need support, bugs that need fixing, design considerations, etc:

Required:

  • LDtk 1.0 files load
  • ldtk types updated
  • new field instances (entity refs, tiles) supported
  • decent solution for using entity refs to create relational components spun off into its own issue #70
  • examples/sample files updated
  • Use iids instead of uids wherever applicable
  • multi-worlds doesn't break plugin

Bonus points:

  • Support for entity instances using field instance tiles for display
  • more comprehensive multi-worlds support
  • parallax layers support (not sure how this would even factor into the api, so maybe best to leave to the user)
  • nine-slice entity display
  • hot reloading for external levels (seems like it'll work now) #1 It won't really work after all, though you can save twice as a workaround

Panic at starting minimal project

Thread main panics when running a minimal setup code.

bevy_ecs_ldtk panic

Code used:

use bevy::prelude::*;
use bevy_ecs_ldtk as ldtk;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugin(ldtk::LdtkPlugin)
        .add_startup_system(setup)
        .insert_resource(ldtk::LevelSelection::Index(0))
        .run();
}

fn setup(mut commands: Commands, ass: Res<AssetServer>) {
    commands.spawn_bundle(OrthographicCameraBundle::new_2d());

    commands.spawn_bundle(ldtk::LdtkWorldBundle {
        ldtk_handle: ass.load("map.ldtk"),
        ..Default::default()
    });
}

Error message:

ERROR wgpu::backend::direct: Handling wgpu errors as fatal by default    
thread 'main' panicked at 'wgpu error: Validation Error

Caused by:
    In CommandEncoder::copy_texture_to_texture
    Copy error
    copy of Y 368..384 would end up overrunning the bounds of the Source texture of Y size 373

', /home/work/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-0.12.0/src/backend/direct.rs:2273:5

AutoLayerRuleGroup does not have field 'collapsed'

I've been working with auto layer rules and I've noticed that the field 'collapsed' is not actually present in autoRuleGroups.
This causes the map load to fail.

Here is an example of what my autoRuleGroup actually looks like:

"autoRuleGroups": [
    {
      "uid": 28,
      "name": "Test",
      "active": true,
      "isOptional": false,
      "rules": []
    }
  ]

I'm rather new to LDTk, but if I understand the documentation correctly auto tile rules are not meant to be used in-engine, and the exact JSON format is not documented so this might be down to a change in recent versions.

I am using LDTk 1.1.1.

Thanks for the awesome library :)

Better typing for `FieldInstance`s

Currently getting the values from FieldInstances is rather annoying, since the value field is just a serde_json::Value. See the typical_2d_platformer example's patrol_setup system for an example of why.

However, we know what types of values a FieldInstance can possible be. Either an integer, float, boolean, string, multilines, file path, color, enum, point, or a list of any of these. So, some rust Enums should do the trick for representing all of these in a single type, and will be much easier to interface with.

Ideally, the serde should just work, but it may require some custom implementations of serde traits.

"relations" feature

With LDtk 1.0, field instances can now store a reference to another entity. Ever since, I've been thinking about how to properly allow users to transform these references into "relational" components that store an Entity object.

Here's the plan.

  1. Create a new default feature called "relations" to make most of the following optional
  2. Make ldtk::FieldInstanceEntityReference both Hash and Component, maybe rename it to just EntityReference
  3. Give all LDtk entities spawned by the plugin an EntityReference component.
  4. When spawning a level, create a HashMap<EntityReference, Entity> of all currently-spawned and soon-to-be-spawned LDtk entities, and pass it as a new argument into the LdtkEntity creation functions.
  5. Create a new derivable LdtkRelation trait for constructing relational components.
  6. Create an #[entity] field attribute for LdtkRelation for marking an Entity field, or maybe just make it smart enough to construct any Entity fields w/o an attribute.
  7. Create a new #[ldtk_relation("FIELD_IDENTIFIER")] field attribute for the LdtkEntity derive that uses the LdtkRelation constructor to create the component from the entity reference field with the given field identifier.

Example:

#[derive(Component, LdtkRelation)]
struct MyRelation {
    #[entity]
    entity: Entity,
    other_info: i32,
}

#[derive(Bundle, LdtkEntity)]
struct MyBundle {
    #[ldtk_relation("my_reference_field_identifier")]
    relation: MyRelation,
    #[sprite_sheet_bundle]
    sprite_sheet_bundle: SpriteSheetBundle,
}

It might also be worth considering supporting deriving LdtkRelation on tuple structs, but I'm not exactly sure how to do that nicely.

Combine colliders in platformer example

Make it so static rigid bodies, like the stone and dirt in the intgrid layer, combine into fewer rigid bodies after spawning. It'll probably be good to just make a new Wall component that flags these intgrid tiles, then have a system that queries for Added<Wall> and uses their TilePos to determine the fewest number of rigid bodies that will make the correct collisions, and spawn them. Make sure these new rigid body entities have the same parent as the Wall entity, so that they get transformed and cleaned up properly by the plugin.

Texture Atlas caching for sprite sheet bundles

Currently, a new texture atlas is created and added to the Assets<TextureAtlas> asset store as part of the logic for the #[sprite_sheet_bundle] field attribute of #[derive(LdtkEntity)]. This means that, even if two entities' visuals are part of the same tileset, two different texture atlases will be created for them, instead of them sharing the same asset with two separate asset handles.

This isn't that big of a deal, since the actual data inside a texture atlas is pretty limited. There shouldn't be any memory leakage either. But still, the current implementation isn't ideal.

Make it so that texture atlases aren't re-added to the asset store if they have been added previously. One approach could be to add an Option<Handle<TextureAtlas>> to the TilesetMap, in addition to the plain image handle. However, I am concerned that this approach may trigger AssetEvent::Modified when we update the field from None to Some, which could lead to unnecessary and constant reloading. An alternative approach might just search the asset store for an appropriate texture atlas handle, but this could be difficult since TextureAtlas isn't Eq/PartialEq.

Hot reloading for tilesets broken

Since bevy_ecs_tilemap switched to texture arrays, I guess this feature hasn't worked and I haven't noticed. Need to make sure to make reloaded textures COPY_SRC!

Add System Labels

Users may need to resolve scheduling irregularities if the systems are all in PreUpdate. Even a simple unit struct or single-variant enum (leaves room for more) could help here

Bevy asset throws an error

Problem

I tried to set up just a basic example but faced the problem

2022-04-20T17:03:51.657636Z  WARN bevy_asset::asset_server: encountered an error while loading an asset:
unknown variant `PrependIndexToLevelFileNames`,
expected `DiscardPreCsvIntGrid` or `IgnoreBackupSuggest` at line 35 column 41

I used an example in basic.rs but I got the same problem in others too.

Environment

Cargo.toml file

[dependencies]
bevy = {version = "0.6", default-features = false}
bevy_ecs_ldtk = "0.2"

main.rs file the same as examples/basic.rs

As I see the problem with the flag property in the .ldtk file.
Bevy assets don't work to play with it "flags": ["PrependIndexToLevelFileNames"]

#[derive(LdtkEntity)] compile error: proc-macro derive produced unparseable tokens

Using #[derive(LdtkEntity)] on a type that has fields with generic type parameters causes a compile error.

Tested on Rust versions:

  • 1.58.1 (db9d1b20b 2022-01-20)
  • 1.60.0-nightly (6abb6385b 2022-01-26)

Tested on bevy_ecs_ldtk versions:

The error is present on all combinations of the above.

To reproduce:

  1. Attempt to compile the following code:
#[allow(unused_imports)]
use bevy::prelude::*;
use bevy_ecs_ldtk::prelude::*;

#[derive(Default)]
struct Generic<T>(T);

#[allow(dead_code)]
#[derive(LdtkEntity)]
struct Entity {
    generic: Generic<u8>,
}

fn main() {}
  1. Receive the following compile errors:
error: comparison operators cannot be chained
  --> src/main.rs:11:21
   |
11 |     generic: Generic<u8>,
   |                     ^  ^
   |
help: use `::<...>` instead of `<...>` to specify type or const arguments
   |
11 |     generic: Generic::<u8>,
   |                     ++

error: proc-macro derive produced unparseable tokens
 --> src/main.rs:9:10
  |
9 | #[derive(LdtkEntity)]
  |          ^^^^^^^^^^

error: could not compile `ecs-ldtk-repro` due to 2 previous errors

As the error above suggests, adding the :: does allow the code to compile successfully, but running rustfmt will promptly remove it again (Preventing this from being a viable solution when using editors with format-on-save enabled).

Multi-level design

The API for dealing with 1 level at a time is pretty nice currently, but it would be good to have better support for multiple level situations.

For example, for games that only load one level at a time, It'd be nice to be able to trigger level loading by just changing the LevelSelection component.

Or, for games that have more of a gridvania or "free" level layout, it'd be nice to be able to load the level neighbors to the current level, automatically give levels transforms based on their location in the gridvania world, and have some functionality for "flagging" entities that shouldn't be despawned when a level is despawned (for example, the player shouldn't despawn if they move two rooms away from the room they spawned in).

The way I'm currently envisioning this is:

  1. The LdtkMapBundle doesn't actually have the tilemap Map on it, and instead the maps exists on separate "level" entities dedicated to a single level, whose parent is the LdtkMapBundle (consider a rename of this bundle)
  2. Some way to provide Settings to ldtk map bundle, either by a component on the LdtkMapBundle or in a separate resource, with the following options:
  • Option to spawn the levels with transforms whose translations are based on the worldX and worldY fields in ldtk
  • Option to spawn level neighbors
  1. Some component inserted into the "level" entities with the Level information
  • probably a Handle<Level> will do here. This has extra benefits of reducing logic differences between external and non-external levels, since the former are already being loaded into handles by the asset server anyway.
  1. Some flag component or enum component or trait method for indicating that an entity shouldn't be unloaded with a level or should have a parent other than the level so it doesn't get despawned recursively.

We need to be careful here about loading/unloading levels and how that will affect the AssetServer change detection. It would be bad to never unload levels or annoying if updating the LevelSelection forced some unnecessary level-reloading of some level neighbors.

Panic on loading level with auto-tiled IntGrid layer with unset tiles

When loading a level with an IntGrid layer that has auto-tile rules, but not every grid cell matches a rule, I frequently (but not always) see the following panic:

thread 'main' panicked at 'Attempting to create an EntityCommands for entity 15v0, which doesn't exist.', /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_transform-0.6.0/src/hierarchy/hierarchy_maintenance_system.rs:69:18
stack backtrace:
   0: rust_begin_unwind
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/std/src/panicking.rs:498:5
   1: core::panicking::panic_fmt
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/panicking.rs:107:14
   2: bevy_ecs::system::commands::Commands::entity
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.6.1/src/system/commands/mod.rs:195:9
   3: bevy_transform::hierarchy::hierarchy_maintenance_system::parent_update_system::{{closure}}
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_transform-0.6.0/src/hierarchy/hierarchy_maintenance_system.rs:69:9
   4: core::iter::traits::iterator::Iterator::for_each::call::{{closure}}
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/iter/traits/iterator.rs:734:29
   5: core::iter::traits::iterator::Iterator::fold
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/iter/traits/iterator.rs:2171:21
   6: core::iter::traits::iterator::Iterator::for_each
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/iter/traits/iterator.rs:737:9
   7: bevy_transform::hierarchy::hierarchy_maintenance_system::parent_update_system
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_transform-0.6.0/src/hierarchy/hierarchy_maintenance_system.rs:68:5
   8: core::ops::function::FnMut::call_mut
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/ops/function.rs:150:5
   9: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/ops/function.rs:269:13
  10: <Func as bevy_ecs::system::function_system::SystemParamFunction<(),Out,(F0,F1,F2,F3),()>>::run::call_inner
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.6.1/src/system/function_system.rs:512:21
  11: <Func as bevy_ecs::system::function_system::SystemParamFunction<(),Out,(F0,F1,F2,F3),()>>::run
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.6.1/src/system/function_system.rs:515:17
  12: <bevy_ecs::system::function_system::FunctionSystem<In,Out,Param,Marker,F> as bevy_ecs::system::system::System>::run_unsafe
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.6.1/src/system/function_system.rs:442:19
  13: bevy_ecs::schedule::executor_parallel::ParallelExecutor::prepare_systems::{{closure}}
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.6.1/src/schedule/executor_parallel.rs:214:30
  14: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/future/mod.rs:80:19
  15: async_executor::Executor::spawn::{{closure}}
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/async-executor-1.4.1/src/lib.rs:144:13
  16: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/future/mod.rs:80:19
  17: async_task::raw::RawTask<F,T,S>::run
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/async-task-4.1.0/src/raw.rs:489:20
  18: async_executor::Executor::try_tick
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/async-executor-1.4.1/src/lib.rs:181:17
  19: bevy_tasks::task_pool::TaskPool::scope::{{closure}}
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_tasks-0.6.0/src/task_pool.rs:222:21
  20: std::thread::local::LocalKey<T>::try_with
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/std/src/thread/local.rs:399:16
  21: std::thread::local::LocalKey<T>::with
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/std/src/thread/local.rs:375:9
  22: bevy_tasks::task_pool::TaskPool::scope
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_tasks-0.6.0/src/task_pool.rs:169:9
  23: <bevy_ecs::schedule::executor_parallel::ParallelExecutor as bevy_ecs::schedule::executor::ParallelSystemExecutor>::run_systems
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.6.1/src/schedule/executor_parallel.rs:122:9
  24: <bevy_ecs::schedule::stage::SystemStage as bevy_ecs::schedule::stage::Stage>::run
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.6.1/src/schedule/stage.rs:850:17
  25: bevy_ecs::schedule::Schedule::run_once
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.6.1/src/schedule/mod.rs:344:13
  26: <bevy_ecs::schedule::Schedule as bevy_ecs::schedule::stage::Stage>::run
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.6.1/src/schedule/mod.rs:362:21
  27: bevy_app::app::App::update
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_app-0.6.0/src/app.rs:112:9
  28: bevy_winit::winit_runner_with::{{closure}}
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_winit-0.6.1/src/lib.rs:504:21
  29: winit::platform_impl::platform::sticky_exit_callback
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/platform_impl/linux/mod.rs:753:5
  30: winit::platform_impl::platform::wayland::event_loop::EventLoop<T>::run_return
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/platform_impl/linux/wayland/event_loop/mod.rs:372:13
  31: winit::platform_impl::platform::wayland::event_loop::EventLoop<T>::run
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/platform_impl/linux/wayland/event_loop/mod.rs:209:9
  32: winit::platform_impl::platform::EventLoop<T>::run
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/platform_impl/linux/mod.rs:669:56
  33: winit::event_loop::EventLoop<T>::run
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.1/src/event_loop.rs:154:9
  34: bevy_winit::run
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_winit-0.6.1/src/lib.rs:171:5
  35: bevy_winit::winit_runner_with
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_winit-0.6.1/src/lib.rs:513:9
  36: bevy_winit::winit_runner
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_winit-0.6.1/src/lib.rs:211:5
  37: core::ops::function::Fn::call
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/ops/function.rs:70:5
  38: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/alloc/src/boxed.rs:1708:9
  39: bevy_app::app::App::run
             at /home/neoraider/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_app-0.6.0/src/app.rs:130:9
  40: detect::main
             at ./src/main.rs:29:2
  41: core::ops::function::FnOnce::call_once
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/ops/function.rs:227:5

Possibly related to #60.

Ability to turn off IntGrid rendering

Hi, It's me with the int grid issues again.

This time, I have the opposite problem as last time. I'm using IntGrid layers with my own special rendering solution and now I get "double rendering" since bevy_ecs_ldtk 0.2.

I think I could get around it by adding a mock auto-tile layer, but it would be nice with a less workaround-y way to do it.

Optional level background color

I've been working on a test project with LDtk, and I've noticed that equal colors that match in LDtk do not match when running in bevy.
The level background (above the floor) and clear color (below the floor) in this screenshot are both equal to #0D2B45, but when rendered in engine they don't match. Ideally of course, they would match, but I would also be happy with being able to turn off level backgrounds rendering which could allow me to do my own parallax effects for a background in future.

image

Level background images

When rendering level backgrounds (soon to be optional #65), the plugin only supports rendering the current level's background color. However, in LDtk, you can also set a background image on levels. The image gets rendered on top of the background color in LDtk. We should support this feature accordingly.

First Release Documentation

At the least, all modules (other than prelude) and all items in prelude should have some description, and plenty should have examples.

Override default for `RegisterLdtkObjects`

By default, the plugin adds IntGridCell or EntityInstance components to entities/intgrid tiles whose identifiers/values have not been registered. It'd be nice to allow the user to change this behavior somehow. This may have strange interactions with #11.

Regressions with tile spacing

Since updating to bevy 0.6/bevy_ecs_tilemap 0.5, loading ldtk files with AutoTile and Tile layers using tileset spacing can lead to crashes.

This may be an upstream issue, and if it is, it's probably not a good idea to hold up a 0.1 release for it. If it's the only choice for getting 0.1 out the door, I'm okay not supporting tileset spacing for AutoTile and Tile layers, so long as it doesn't lead to crashes (maybe a warning?)

Update to new renderer

Might be a good idea to try out the new-renderer branch of bevy_ecs_tilemap as well as updating the bevy revision to see how the new renderer may affect this plugin.

`GridCoords` component w/ LdtkEntity and LdtkIntCell support

There should be a GridCoords component w/ x and y i32 fields. Give it conversion to/from IVec2.

Add a new attribute #[grid_coords] to LdtkEntity and LdtkIntCell derive traits which constructs the component with its grid-based position in the level (y+). This can be determined from a LayerInstance and EntityInstance in LdtkEntity, but LdtkIntCell will need some additional information to figure out the proper coords.

Make it clear in the docs that this component does not update the transform, nor visa versa. That should be left up to the user since there's plenty of scenarios where this needs to be a bit custom (if they want to do transitions w/ bevy_easings, for example)

LDTK Edge Cases

It would be nice to have some support for more difficult ldtk files. This issue will be used to track known edge cases before the first release.

Not all of these will be supported for 0.1, and not all of these will be supported at all if they are deemed not worth the cost of maintenance.

  • flip_x and flip_y
  • tileset padding
  • layer offsets
  • multiple transparent autotiles sharing tile
  • different TileRenderModes for entities (current behavior is basically the Stretch mode)
  • layer tile sizes differing from tileset tile sizes (only partially done in #17)
  • autotile tiles rendering halfway inbetween tiles due to their rules having a strange pivot+rectangle config
  • entity definitions whose sizes are different than the tileset grid size of their editor visual

Make `LdtkIntCell` and `LdtkEntity` not require `Bundle`

The registration functions and phantom types should still require the LdtkObjects to also be Bundle, but it would be harmless to be able to give individual Components the access available to these traits with their construction, rather than reserving that accessibility for Bundles.

An IntGrid example would be cool

I've been using int grids for simple colored tiles because it's a lot simpler than maintaining a 1xN texture with colored pixels

image

image

Would be great with an example that showed how to load such levels.

Access tile data

Hi,

Ldtk makes it possible to link data to tiles of a tile-set (either arbitrary text or enum-based)

It would be nice if there was a TileData(or equivalent) component inserted on tiles that have data defined so that we could query them and have logic based on the data we defined in ldtk.

Chatty bevy_ecs_tilemap warnings for IntGrid layers that aren't AutoTile

Title.
This is because texture arrays require textures to be marked as COPY_DST and COPY_SRC, and the current implementation for IntGrid layers is to make them tilemap layers, regardless of whether or not they have visuals associated with them. It's just that, when there are no AutoTiles, the layer just uses the bevy default image handle, and when you mark the default handle accordingly, a crash occurs.

I tried to just change the log filters but there's a bug with log filters in bevy 0.6 where you have to set them BEFORE adding default plugins. It isn't an option to just make users add our plugin before default plugins, because that breaks TilemapPlugin.

If you run into this, just insert a log settings resource for it before DefaultPlugins, or update your IntGrid layer so it has an Auto-layer tileset in the Layers tab of LDtk.

    App::new()
        .insert_resource(bevy::log::LogSettings {
            filter: "bevy_ecs_tilemap::render::pipeline=error,wgpu=error".to_string(),
            level: bevy::log::Level::INFO,
        })
        .add_plugins(DefaultPlugins)
        .add_plugin(LdtkPlugin)

Layer selection for `RegisterLdtkObjects`

For more complicated Ldtk files, there will be many different Entities layers and IntGrid layers. So, it would be nice to allow users to register objects for a specific layer. This is especially pertinent for IntGrid layers.

We should add more functions to RegisterLdtkObjects to allow this. A new LayerSelection enum should be created, similar to LevelSelection with an additional Any variant (the default). register_ldtk_entity_for_layer and register_ldtk_int_cell_for_layer should now be the new core functions of RegisterLdtkObjects, with register_ldtk_entity and register_int_cell taking fewer arguments and supplying LayerSelection::Any to the former functions respectively.

Layer opacity

Add layer opacity support by altering the alpha of every Tile::color on that layer. No need to do so if the opacity is 100%.

This change won't really work until the new version of bevy_ecs_tilemap. Some bug in 0.5 makes the Tile::color not multiply the texture properly.

Better Transform Helpers

The current utils functions related to transform calculation are ok but could be better.
calculate_transform_from_tile_pos, for example, only calculates the translation component of a transform, and should be generalized or renamed to reflect that.

There's also a need for being able to calculate bevy translations from ldtk grid positions, or ldtk pixel positions, which isn't really provided by the existing utils functions. However, these calculations require access to the height of a level, so it might make sense to define methods for them on some ldtk object, like the LdtkAsset.

Unfortunately, the level height is not accessible in LdtkEntity and LdtkIntCell methods, which makes it difficult to, for example, figure out the transform for an entity's field instance of type Point. It may be worth passing in the LayerInstance to these traits for such use cases.

This goes without mentioning the transform of the map itself, or of levels within that map (which may be implemented at some point). Should the resulting translations be relative to the map?

Obviously I haven't thought this all the way through, but want to leave an issue with my thoughts for later.

Custom constructors for some `LdtkEntity` field attributes

The sprite_sheet_bundle, sprite_bundle, and worldly field attribute constructions in bevy_ecs_ldtk_macros are identical to just using #[ldtk_entity]. I think this is a little strange. I think it could potentially cause some confusion with their usage, especially when debugging. For example, it's a bit weird that you can use #[worldly] on any sub-LdtkEntity.

A small refactor would be to make more minimal constructors for these types, and have their LdtkEntity impls just use those constructors. Then, have these field attributes use those minimal constructors.

System-based LdtkEntity and LdtkIntCell

There are two main drawbacks for using LdtkEntity and LdtkIntCell

  1. For mildly complex cases, implementing these traits manually is super verbose (many method arguments)
  2. For more complex cases, the parameters may not give you enough access to the world

Basically, these two traits are very opinionated about what the user might need when they are spawning bundles from the Entity and IntGrid layers. This can be mildly annoying. I think an ideal solution would be to use bevy systems for spawning. That way, users can define exactly what they need from the world, and can feel free to not ask for what they don't need, reducing boilerplate.

To be clear, I'm referring to users being able to write system-like functions/methods for the Entity and IntGrid registration, hooking into the spawning process. Not just normal systems that do spawning afterward. Users can do the latter now, but it does have some quirks, like their entities not spawning until the update AFTER the level spawns, or having to do some clone-fu to avoid overwriting the plugin's calculated transformation, or having to manually match for the entity identifier or intgrid value you are interested in.

Not sure how the exact implementation of this would work (probably using some dark, forbidden bevy traits like FunctionSystem). I'd like the derive traits to be at least as useful as they are now. I'm okay with the design of the macros changing somewhat as long as it's an improvement.

I don't have much of an opinion on whether LdtkEntity and LdtkIntCell should even remain traits with this change. I feel like it would probably be pushing rust's generic features to the limits to have generic trait-method parameters, but idk. I may slightly prefer that they remain traits just to make typing easier as they are passed around the plugin.

This change may result in the level-spawning system becoming exclusive. This is not ideal, but I can't really imagine an alternative. If somehow the level-spawning system can be generic over whatever the user defines in their spawning systems that they register to the app, that would probably be ideal, but it sounds impossible.

Also, not sure how exactly to pass the LDtk data to these systems (EntityInstance, LayerInstance, IntGridCell). Maybe an In parameter? A custom system param?

Use `Vec2` and `IVec2` in ldtk module

It turns out, the serialization/deserialization of IVec2 and Vec2 plays nicely with ldtk. This realization was the final "pro" needed for me to decide that this change is worth it.

For any point values in the ldtk module (currently Vec<i32> or Vec<f32>, with the assumption that they only have 2 items), change their types to Vec2 and IVec2. Update all usages accordingly. Add it to the list of changes in the ldtk module doc.

Clear color settings enum

for LdtkSettings::set_clear_color, I'd like to change it so it is:

  1. Off by default
  2. Has an additional option for using the current level's bg color instead of the editor bg color

Setting the clear color requires waiting for the LdtkAsset to load to be able to find out what color to set it to. As a result, we can't use the convenient App::init_resource(ClearColor...), since we don't know the contents of the ldtk file at that point. So, in the system that sets the clear color, it always gets overwritten. I think users will often:

  1. See that the clear color is different after adding the plugin
  2. Try to change the clear color if they don't like it using a App::insert_resource(ClearColor...)
  3. Get confused as to why their clear color change didn't work
  4. Maybe eventually find the set_clear_color option, but it might not be discoverable enough.

So, we could either improve step 4 by improving the discoverability of that option, or avoid all 4 steps by just leaving it off by default. I think the latter makes a lot of sense.

Also, the editor bg color was used originally to make bevy match LDtk's visuals by default, but I've realized that this can be unexpected behavior, and that conceptually a level bg color may be more intuitive. So, I'd like to make this an enum instead of a bool, with an option to do nothing (default), an option to set the clear color to the LevelSelection's background color, and an option to set the clear color to the editor bg color (current behavior).

I'm not sure at this time whether or not this should be a field in LdtkSettings or just its own separate resource. I might be slightly leaning towards the former.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.