#bevy_ecs_tilemap

3448 messages · Page 4 of 4 (latest)

pliant portal
#

I'm making an ARPG where side effects are decoupled from abilities

fn ability_attack(
  mut commands: Commands,
  mut tilemap_query: Query<(
    &TilemapSize,
    &TilemapGridSize,
    &TilemapType,
    &mut TileStorage,
    &Transform,
  )>,
  cursor_position: Res<CursorPosition>,
  action_state_query: Query<&ActionState<Ability>>,
) {
  for action_state in action_state_query.iter() {
    if action_state.just_pressed(&Ability::Attack) {
      for (map_size, grid_size, map_type, mut tile_storage, map_transform) in
        tilemap_query.iter_mut()
      {
        // ...

        // Once we have a world position we can transform it into a possible tile position.
        if let Some(tile_pos) =
          TilePos::from_world_pos(&cursor_in_map_pos, map_size, grid_size, map_type)
        {
          if let Some(tile_entity) = tile_storage.get(&tile_pos) {
            commands
              .entity(tile_entity)
              .insert((EffectDamageTile { damage: 1.0, },));
          }
        }
      }
    }
  }
}

This is all good, but when I apply the damage on a different system there's no way to update the tile storages by entity

fn apply_tile_damage(
  mut commands: Commands,
  effect_query: Query<(Entity, &EffectDamageTile)>,
  mut tilemap_query: Query<&mut TileStorage>,
) {
  for (entity, effect, prior_damage, noise) in &effect_query {
      for mut tile_storage in &mut tilemap_query {
        if let Some(tile_entity) = tile_storage.get(&effect.tile_pos) {
          tile_storage.remove(entity); // <- this impl doesn't exist
        }
      }
      commands.entity(entity).despawn();
  }
}

You can only do tile_storage.remove with TilePos, which is local to each chunk 💀

#

so I was like, fuck it, I'm just not gonna bother with tile storage and despawn the entity, but then woop:

thread '<unnamed>' panicked at src\pawn.rs:196:16:
Attempting to create an EntityCommands for entity 502v1#4294967798, which doesn't exist.
#

because the ability_attack system relies on tile_storage to get the tile

unreal condor
#

I haven't really dealt with chunking in my own stuff, so I am slightly uninformed, but maybe the info will help.

  • Right now TileStorage is only used by bevy_ecs_tilemap to clean up tiles when you despawn a tilemap/chunk. If your tiles are children of the chunk, or if you have some other way of despawning individual tiles associated with a chunk, you might not need to use it at all.
  • Tiles keep a reference to their tilemap/chunk in a TilemapId component, so you can use that to directly look up the correct TileStorage. tilemap_query.get(tilemap_id.0)
  • You can probably do some simple math to get a chunk relative transform / tilepos.
velvet hornet
#

yeah, its worth noting as well that bevy_ecs_tilemap doesn't have a built-in high-level abstraction to control chunking, so you are expected to build that high-level abstraction on top of the chunking capability yourself if you want your application code to ignore that chunking exists.

Also, as was mentioned, that TileStorage is effectively "just" a user-maintained index already, so you could maintain your own index for your own access patterns. There's really nothing special about it, the current TileStorage is a fairly commonly used form of that index.

Two other notes:

4x4 chunks feels like a small number, what's the deciding factor for using 4x4 chunks? Not that the problem goes away with larger chunks (especially if you're doing infinite maps) but 4x4 is definitely making it more of an issue (smaller chunks == more TileStorages, etc).

and a bit tangentially, that first codeblock looks like picking to me. We should do an official picking implementation at some point. (the only thing I have a hard time reconciling with picking is layers of maps but maybe that's just multiple hit targets).

pliant portal
#

Thanks y'all, it definitely sounds like picking! I had a little nap and to mull it over and I think I'm trying to replicate the example from the readme:

struct Damage {
    amount: u32,
}

fn update_damage(
    mut query: Query<(&mut TileTexture, &Damage), Changed<Damage>>,
) {
    for (mut tile_texture, damage) in query.iter_mut() {
        tile_texture.0 = TILE_DAMAGE_OFFSET + damage.amount;
    }
}

^ this feels like bottom up, while picking feels like top down

pliant portal
#

Just tried your suggestion @unreal condor, this worked!

fn apply_tile_damage(
  mut commands: Commands,
  effect_query: Query<(
    Entity,
    &EffectDamageTile,
    Option<&Damage>,
    &NoiseValues,
    &TilemapId,
    &TilePos,
  )>,
  mut tilemap_query: Query<&mut TileStorage>,
) {
  for (entity, effect, prior_damage, noise, tilemap_id, tile_pos) in &effect_query {
    let damage = if let Some(component) = prior_damage {
      component.0
    } else {
      0.0
    };

    let new_damage = damage + effect.damage;

    if new_damage >= noise.density {
      if let Ok(mut tile_storage) = tilemap_query.get_mut(tilemap_id.0) {
        tile_storage.remove(&tile_pos);
      }

      commands.entity(entity).despawn();
    } else {
      commands
        .entity(entity)
        .remove::<Damage>()
        .insert(Damage(new_damage));
    }
  }
}
pliant portal
#

Y'all how would you set a custom material param per tile? Looking at the custom shader example, my first thought is to add a param like this to the material and then somehow derive a local tile index in the shader

#import bevy_ecs_tilemap::common::process_fragment
#import bevy_ecs_tilemap::vertex_output::MeshVertexOutput
#import bevy_sprite::mesh2d_view_bindings::globals


struct MyMaterial {
    tile_damage: mat4x4<f32> // dimensions based on chunk size
};

@group(3) @binding(0)
var<uniform> material: MyMaterial;

@fragment
fn fragment(in: MeshVertexOutput) -> @location(0) vec4<f32> {
    var color = process_fragment(in);
    // sample tile_damage and change color somehow
    return color;
}
pliant portal
#

but this feels wrong on an architectural level, my second thought is to somehow write to a shared buffer and have the materials read from it, rather than packaging game data into chunk materials like that

trim spade
#

Hey, I'm trying to figure out how I can blend a texture against the bevy_ecs_tilemap tiles. I'm trying to replicate a feature in Godot where I can multiplicatively blend a texture with what is beneath it. Is it possible to have some viewport (bevy camera?) to render an area of the tilemap (i.e. what is visible from bevy_ecs_tilemap on screen) to a texture, so that I can then do the multiplicative blending in a fragment shader?

velvet hornet
# trim spade Hey, I'm trying to figure out how I can blend a texture against the bevy_ecs_til...

you can definitely render cameras to textures and can also do custom post-processing. Sounds like you want a post-processing pass or want to use a custom material. So you have options. depends on what you want to do.

trim spade
# velvet hornet you can definitely render cameras to textures and can also do custom post-proces...

Thanks again, I have dug into these examples and I have a small PoC of what I want to do by converting the post-processing example for 2D and integrating the ecs tilemap lib.

However, I did initially look at the custom shader example in bevy_ecs_tilemap. I am not sure that it is possible due to the rendering approach of the lib, but this material that we can apply custom shaders to, is it possible to get this as a texture (once it has been rendered) into my own render pipeline? I'm guessing it isn't just one texture making this a bit more complicated. What I was hoping to do is to just get the GpuImage from the handle as I do for my compute shader pipeline queue bind groups system. I suspect it isn't as simple as that?

pliant portal
#

@trim spade I would do the blending in the tilemap fragment shader

@fragment
fn fragment(in: MeshVertexOutput) -> @location(0) vec4<f32> {
    var color = process_fragment(in);
    // mix colors here
    return color
}
#

Hey folks, is it possible to get the world position of the tile in a custom shader? The MeshVertexOutput position is in clip space and it gives me this smooth gradient when I do this:

@fragment
fn fragment(in: MeshVertexOutput) -> @location(0) vec4<f32> {
    let color = vec3(in.position.x) / 10000.0;
    return vec4(color, 1.0);
}

My goal is to get a stable vec2<i32> index per tile in the fragment shader so that I can use it to access a buffer.

pliant portal
#

If I try transforming with view.world_from_clip

#import bevy_ecs_tilemap::common::{tilemap_data, process_fragment}
#import bevy_ecs_tilemap::vertex_output::MeshVertexOutput
#import bevy_sprite::mesh2d_view_bindings::{view}


@fragment
fn fragment(in: MeshVertexOutput) -> @location(0) vec4<f32> {
    let world_pos = view.world_from_clip * in.position;
    let color = vec3(world_pos.xyz) / 100000.0;
    return vec4(color, 1.0);
}

The gradient still looks like its in clip space. I find that super weird because it seems in the vertex shader multiplies the mesh position to the view.clip_from_world

pliant portal
#

I figured it out 🚀 ended up using storage_position

fn get_tile_damage(in: MeshVertexOutput) -> u32 {
    let x = in.storage_position.x;
    let y = in.storage_position.y;
    let z = material.chunk_index;
    let index = x + chunk_size * (y + chunk_size * z);

    return chunk_data[index];
}


@fragment
fn fragment(in: MeshVertexOutput) -> @location(0) vec4<f32> {
    let base_color = process_fragment(in);

    let damage = f32(get_tile_damage(in)) / 10.0;
    let damage_color = vec4(damage, damage, damage, 1.0);

    return mix(base_color, damage_color, 0.5);
}
velvet hornet
#

on the surface seems fine to me, I'll do some more testing and whatnot if you're also positive about it

unreal condor
#

can't look close just this minute but

  • if we're adding support for it, I feel like it might as well be required
  • imo the current get_tilemap_center_transform is quite wacky and I wouldn't mind seeing it go away
  • if we really want to add it without breaking changes then I guess above two points are okay
  • i don't immediately understand why we need the separate extracted_anchors
    but yeah, generally positive
wind tide
#

the example shows a helpers mod, but where its?

unreal condor
#

in examples/helpers.

wind tide
#

seens doenst exist anymore

wind tide
#

yes but the titled example does not exist anymore for this

#

the 3d iso example

unreal condor
wind tide
#

more examples are outdated

wind tide
#

those are the only suggestions for helpers here

unreal condor
#

Yeah that was a typo, I accidentally threw in an angle bracket. I fixed the link.

wind tide
#

my cargo is right btw

unreal condor
#

You need to copy the helpers into your project if you want to use them.

#

They are just example code.

wind tide
#

ooooooooooooo

#

thanks brother

wind tide
#

i used the basic example and changed this

unreal condor
#

Your TilemapTileSize seems incorrect.

wind tide
#

hmm, how so, isometric is 2:1 ratio

#

anyway

unreal condor
#

It refers to the size of the tiles in your tile asset. TilemapGridSize probably should have y value halved though. I'm not super familiar with the iso stuff though.

wind tide
#

hmm iam trying use the stuff from Tiled

#

but seens return errors

#

i look the examples

#

and even modified the Map.tmx myself to match the example one

#

but no sucess

wind tide
#

everything goes wrong lol

#

Cause idk why its croping

wind tide
#

@brisk path

velvet hornet
velvet hornet
wind tide
#

nor perfect like the tiled

#

see

#
use bevy::prelude::*;
use bevy::ui::UiSystem::Focus;
use bevy_ecs_tiled::TiledMapPlugin;
use bevy_ecs_tilemap::TilemapPlugin;
use bevy_ecs_tiled::prelude::*;
use bevy_ecs_tilemap::prelude::*;

mod tilemap;

fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
    // Spawn a 2D camera (required by Bevy)
    commands.spawn(Camera2d);

    // Load the map ...
    let map_handle: Handle<TiledMap> = asset_server.load("Overworld.tmx");

    // ... then spawn it !
    let mut map_entity = commands.spawn(TiledMapHandle(map_handle));

    // You can eventually add some extra settings to your map
    map_entity.insert((
        TiledMapSettings {
            layer_positioning: LayerPositioning::Centered,
            ..default()
        },
        TilemapRenderSettings::default(),
    ));
}

fn main() {
    App::new()
        .add_plugins((DefaultPlugins,TilemapPlugin,TiledMapPlugin::default()))
        .add_systems(Startup, startup)
        .run();
}
unreal condor
#

The y_sort: true part of the iso_3d example is important

wind tide
#

Thanks goat i Will try when iam back

unreal condor
#

re: #596

I feel like we are hampered by the excessive amount of separate components we use. I would really like to just be able to do

let tile_center = map.world_pos(tile_pos);

where map is like

struct Tilemap {
  map_size: UVec2,
  map_type: TilemapType,
  tile_size: Vec2,
  grid_size: Vec2,
  // possibly more
}

mirroring the sort of transformation that Bevy's Sprite component had in Bevy 0.15.

This would also allow us to delete a bunch of code related to the newtyped vecs.

velvet hornet
#

also I wish we had used different terms for render chunks and tilemap chunks 😆

wind tide
#

nvm

#

even with y sort still bad

#
use bevy::prelude::*;
use bevy::ui::UiSystem::Focus;
use bevy_ecs_tiled::TiledMapPlugin;
use bevy_ecs_tilemap::TilemapPlugin;
use bevy_ecs_tiled::prelude::*;
use bevy_ecs_tilemap::prelude::*;

mod tilemap;

fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
    // Spawn a 2D camera (required by Bevy)
    commands.spawn(Camera2d);

    // Load the map ...
    let map_handle: Handle<TiledMap> = asset_server.load("Overworld.tmx");

    // ... then spawn it !
    let mut map_entity = commands.spawn(
        TiledMapHandle(map_handle)
    );

    // You can eventually add some extra settings to your map
    map_entity.insert((
        TiledMapSettings {
            layer_positioning: LayerPositioning::Centered,
            ..default()
        },
        TilemapRenderSettings{
            y_sort: true,
            ..default()
        },
    ));
}

fn main() {
    App::new()
        .add_plugins((DefaultPlugins,TilemapPlugin,TiledMapPlugin::default()))
        .add_systems(Startup, startup)
        .run();
}
#

so yes idk why its wrong

unreal condor
brisk path
# unreal condor I'm not super familiar with `bevy_ecs_tiled`. But this seems relevant: https://...

Which is wrong the size on the X axis should be the size of the tilemap.

render_chunk_size: UVec2::new(tilemap_size.x, 1),

I can't advocate for bevy_ecs_tilemap to render tilemaps that are 3D isometric tilemaps as its really not designed properly to render those efficiently. There are other issues as well where iso tile picking will not work correctly and the logic for picking a 3D iso tile is very very complex.

wind tide
#

?

#

The example is wrong?

brisk path
wind tide
#

So How to fix keeping performance?

#

Reading the example I remember on Unity you also have to set it to render individual and not per chunck

#

For isometric tilemaps

brisk path
# wind tide So How to fix keeping performance?

you can set the render chunk size to be tilemap size on the x axis and 1 on the y axis. this allows for proper Y sorting.
Even this though is not performant enough for very large maps. if you need large maps I suggest writing your own tilemap renderer. There are resources online which should help

wind tide
#

I Would need remake the entire tilemap system lol

wind tide
brisk path
wind tide
#

Who did it so I could ask

wind tide
brisk path
brisk path
#

There are hints on how I do this:
#rendering-dev message

#

And a more zoomed in screenshot:

wind tide
brisk path
wind tide
#

Why

brisk path
#

I don't have the time

wind tide
#

I see

#

Lmao

#

I also have no idea How add a z-depth buffer

#

Lack of examples

#

Thanks anyway bro

rare bramble
#

Hey,
Thanks for the heads up, will fix the iso example and use x=64, which is the default chunk size.
Using bevy_ecs_tiled, you could technically get the map size before spawning it, with assets server events and waiting for the tiled map to be parsed before actually spawning it in Bevy. But I don't think it's worth the extra complexity. You should instead set an arbitrary "large enough" value for your chunk (I believe 64 should be fine).

wind tide
#

Hey @brisk path one last question, If you didnt implemented z-depth buffer layer How your system is able to have depth on isometric tiles? Cause one of examples there is a isometric tilemap with 3 Floors, that have depth Sense, iam confused now

wind tide
#

@rare bramble how can i enable the map now instead need cycle it?

#

i dont want have to press a button to cycle it

#

i mean i cant even select the map i want display, and it still renders on a wrong way

rare bramble
wind tide
#

okie but i tryed loaded on the other way arround and nothing happens, let me show

rare bramble
#

I think you want something like that:

fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn((
        TiledMapHandle(asset_server.load("map.tmx")),
        TilemapRenderSettings {
            render_chunk_size: UVec2::new(64, 1),
            y_sort: true,
        },
    ));
}
wind tide
#

this does help but stil the tiles are not rendered like the tiled app

rare bramble
#

Sorry, no clue: I don't use isometric myself and I did not see that with the test maps I'm using.
Couple things to check: do you use isometric "diamond" map ? Isometric "staggered" maps are not supported.
Also, is it doing the same thing if you use a render chunk of (1,1) ?
As said earlier, it's not good perf wise but could give some insights to check it out
Anyway, please keep in mind that isometric maps are currently not well supported, notably if you try to use physics colliders with them.

wind tide
#

sad i wanted make a with bevy but this tilemap limitation is sad,well i tried

#

thanks anyway sir

lethal cosmos
#

Quick question, after taking the basic example of the crates repository and setting the TilemapTileSize to (64, 64), the map doesn't seem to be rendering anymore? Is there some requirement for the tile size to be the same size as the rendered picture?

unreal condor
#

TilemapTileSize is the size in pixels of the tiles in the image asset.
TilemapGridSize can control tile spacing.
To control the size of tiles on screen, your only option is manipulating the 2d camera.

pastel grove
#

Hey all, I just realized there's a channel for this great crate. I submitted a PR a little back and am looking for reviewers. I added a summary at the end that can catch you up on the high-level changes without you having to read through the PR's history.

GitHub

Hi, thank you for all your work on this crate! It's been incredibly useful.
I had a specific need for controlling how the tilemap was positioned. I specifically wanted it to be positioned f...

pastel grove
unreal condor
#

I was just going to point to that, I think I haven't looked at the PR since then. I am not opposed to merging your PR before that happens. Sorry I haven't gotten around to actually reviewing yet.

pastel grove
#

The tile_pos.center_in_world(&map_size, &grid_size, &map_type, &anchor) is currently a thorn in my side, so I'd be willing to put some work in to make it less cumbersome as a separate PR possibly.

#

In trying to get the position of tiles, I think it should certainly be available using a center_in_world() like API or even better @unreal condor's suggestion: let tile_center = map.world_pos(tile_pos);, but because each tile is an entity, I played around with populating the tile with a Transform component. The renderer doesn't need it or use it, which I like about its design, but it's more like a user affordance since if you want to label a tile, you can add child to it with Text2d. Nice thing is it's just a system that user can elect to run to opt-in. I wondered what people thought of that.

unreal condor
velvet hornet
pastel grove
pastel grove
#

sighs pushes new 1.85.0 lint fix.

sleek bloom
#

Hey guys I'm experimenting with a custom material for my tilemap and I'm having issues with a ShaderStorageBuffer.

I have light data that I sync in the buffer and pass to my Sprite and Tilemap materials. For the sprite Material2d, the shader receives the updates as expected but my material for the tilemap only gets the initial value and never updates. Am I doing something wrong that's incompatible with bevy_ecs_tilemap bindings? Any gotchas I should be aware? I'm pretty new to this.

map shader:

#import bevy_ecs_tilemap::vertex_output::MeshVertexOutput
#import bevy_sprite::mesh2d_view_bindings::globals
#import bevy_ecs_tilemap::common::process_fragment
#import bevy_ecs_tilemap::common::tilemap_data
#import bevy_ecs_tilemap::common::mesh

@group(3) @binding(0) var normal: texture_2d<f32>;
@group(3) @binding(1) var normal_samp: sampler;
@group(3) @binding(2) var<storage, read> lights: array<Light>;

struct Light {
    color: vec3<f32>,
    intensity: f32,
    position: vec2<f32>,
    max_distance: f32,
};

fn isLightZero(light: Light) -> bool {
    return all(light.color == vec3<f32>(0.0)) &&
           (light.intensity == 0.0) &&
           all(light.position == vec2<f32>(0.0)) &&
           (light.max_distance == 0.0);
}

@fragment
fn fragment(in: MeshVertexOutput) -> @location(0) vec4<f32> {

    let color = process_fragment(in);
    let first = lights[0];
    if isLightZero(first) {
        return vec4<f32>(0.0, 0.0, 0.0, 1.0);
    }
    return color;
}

Material:

#[derive(Asset, Reflect, AsBindGroup, Debug, Clone, Default)]
pub struct LitMapMat {
    #[texture(0)]
    #[sampler(1)]
    pub normal: Option<Handle<Image>>,

    #[storage(2, read_only)]
    pub lights: Handle<ShaderStorageBuffer>,
}

impl MaterialTilemap for LitMapMat {
    fn fragment_shader() -> ShaderRef {
        "shaders/map.wgsl".into()
    }
}

To use my Material on the tilemap I update it after it is spawned (maybe this is a problem?) because I didn't find a way to do it through the bevy_ecs_tiled API:

use bevy::{prelude::*, render::render_resource::TextureFormat};
use bevy_ecs_tiled::prelude::*;
use bevy_ecs_tilemap::prelude::{MaterialTilemapHandle, StandardTilemapMaterial};

use crate::{material::LitMapMat, LightBuffer};

pub struct MapPlugin;

impl Plugin for MapPlugin {
    fn build(&self, app: &mut App) {
        app.register_type::<NormalMapTex>()
            .add_observer(on_layer_added)
            .add_systems(Startup, load_map);
    }
}

fn load_map(mut commands: Commands, asset_server: Res<AssetServer>) {
    let map_handle: Handle<TiledMap> = asset_server.load("map.tmx");
    commands.spawn((TiledMapHandle(map_handle),));

    let normal_map = asset_server.load("tileset-normal.png");

    commands.insert_resource(NormalMapTex(normal_map));
}

fn on_layer_added(
    _trigger: Trigger<TiledLayerCreated>,
    tilelayer_q: Query<Entity, With<TiledMapTileLayerForTileset>>,
    map_normal: Res<NormalMapTex>,
    light_buffer: Res<LightBuffer>,
    mut map_materials: ResMut<Assets<LitMapMat>>,
    mut commands: Commands,
) {
    for tile_layer in tilelayer_q.iter() {
        let material = MaterialTilemapHandle::from(map_materials.add(LitMapMat {
            normal: Some(map_normal.0.clone()),
            lights: light_buffer.0.clone(),
        }));
        commands
            .entity(tile_layer)
            .remove::<MaterialTilemapHandle<StandardTilemapMaterial>>();
        commands.entity(tile_layer).insert(material);
    }
}
rare bramble
#

Never played with custom shaders so I won't be a great help. However, I believe you should use a TiledMapCreated trigger since you only care about the map being loaded. By using a TiledLayerCreated trigger, your function will be called once for each layer in your map which feels wrong if your map has several.

sleek bloom
#

ahh that's right, thanks I'll adjust that.

pastel grove
unreal condor
#

I have time for... a glance, and pressing the CI button.

pastel grove
#

Awesome, thanks! Addressed your comments, @unreal condor.

dusty hinge
#

I'm having a couple issues, it seems like the map isn't reacting as I'd expect to changing the Transform component, so for example if I put the scale on the transform as (0.1, 0.1, 1.0), then the entire map just disappears. The reason I'm trying to change the scale is because the tilemap is using size in pixels, but I have changed the camera to be ~10 units across, so the tilemap is absolutely massive.
But then for debugging purposes I started zooming the camera out, but I'm getting a lot of lines inbetween the tiles, is this a common problem?

#

That grey diamond is a single tile for the record

#

Ah, I figured out where my map keeps going, this is with the scale (0.5, 0.5, 1.0)

#

I suppose what I've done is scale each chunk, but not the chunk's location?

dusty hinge
#

This is so strange, if I change the Transform of the tilemap later, then it recalculates and everything is correct, but at spawn time it's wrong 🤔

pastel grove
#

I was a little more thoughtful with the "anchor" example and stopped hijacking the hex_neighbors example. PR updated.

pastel grove
#

Anything else the above PR ought to do? I guess it needs a reviewer's approval.

unreal condor
#

Did a sort of weak review before heading out the door for a week, but I'd be happy to see this merged before the Bevy 0.16 work starts.

static cipher
#

Not sure if anyone else has started, but I've been going through some of the low hanging fruit for 0.16 support. I'm not super familiar with the codebase yet so just solving stuff like renames and other simple fixes

static cipher
static cipher
#

Or perhaps it's the new VisibilityClass stuff

static cipher
#

I believe I fixed visibility, now just need to figure out a bind group error.

pastel grove
#

Dang. I’m gonna be sad if my anchor PR doesn’t get merged before 0.16 comes in.

pastel grove
static cipher
static cipher
#

I’d also love to bring back the required component changes

static cipher
#

Got it working!

pastel grove
static cipher
#

Just looked through your PR, I don't think we have many conflicts between our branches!

#

This is my own implementation that just looks for tile storage changes and runs through all of the solid tile positions, filtering possible stamps and picking one randomly using a weighted distribution sample. I think it could be made pretty nice with an API like AnimatedTile -- you mark a tile with something like RandomTileGroupId and then add the possible stamps to a tile group on the tilemap. Each stamp would define its offset, size, and weight.

somber flame
#

does anyone have a solution for generating collision meshes based on tileenumtags?

#

im using avian, if that helps

velvet hornet
velvet hornet
static cipher
velvet hornet
# static cipher Hey <@103513724052082688> -- wondering if you have any input on potentially repl...

from a use-case perspective, TileStorage is mostly just the most common indexing strategy. TilePos -> Entity. From that perspective I'm not sure how the suggested approach would replace that indexing strategy. How would you get an Entity if you have a TilePos?

at a higher level, I intend to do the 0.16 release (with anchor) so that upgrading is easy for people before merging anything like that change.

static cipher
#

Yeah sorry replacing was a bad word -- more like updating TileStorage to be a relationship and renaming it so it's clearer as such. I imagine the indexing would still be there. I'm just not entirely sure it's possible with the current relationship api.

velvet hornet
#

there were indexing experiments that I don't think made it into 0.16

static cipher
#

I wonder with hooks/observers if it would be possible to maintain the index along with the relationship?

#

maybe keeping that in sync would be a pain.

velvet hornet
static cipher
#

oh interesting I see -- yeah that seems ideal

velvet hornet
#

so there's work happening and I'm open to changes, but it'll be after the 0.16 tilemap release. I would like to not change TileStorage twice in a row (ex: again for 0.17) but exploring options is welcomed

#

iirc, for #582 I think we're looking for perf benchmarking for more information before making decisions

#

bevy keeps improving transform propagation perf, so it is nice to just ride that while its happening too

static cipher
#

yeah I also wasn't sure if you could opt in to transform propagation with custom relationships or not.

static cipher
velvet hornet
static cipher
#

ok tyty

#

Also not sure if you saw but there was some discussion around a working group to get first-class tilemap rendering support going: #general message

#

I wonder if now would be a good time to try and get that ball rolling

velvet hornet
#

honestly I'm not even sure a working group is necessary. A PR with a tilemap rendering implementation based on past discussions in #rendering would probably land.

static cipher
#

Yeah IceSentry did mention someone else had been working on a PR but they got busy with other things.

velvet hornet
#

there's the chat history in the rendering channels from that attempt (and other discussions) if you want to take a crack at it

pastel grove
#

Anchor PR merged! [fist pump] Yes! I was worried this one wasn’t gonna make it after a while.

#

Thanks, @velvet hornet!

velvet hornet
velvet hornet
unreal condor
#

I'll do some more testing later, but generally LGTM. Perfect timing, starting to feel human after post-vacation covid.

velvet hornet
static cipher
velvet hornet
#

we saw improvements last cycle too in the transform algos

static cipher
#

I was trying to think of use cases for even moving tiles at all, I can't really think of any.

#

Moving entire maps, sure -- but the tiles themselves should always be clean

#

I guess you still incur the initial propagation

velvet hornet
#

if you think of tilemaps as basically "runtime pngs" then yeah I see what you're saying

static cipher
#

yeah that's what I was thinking

#

like in the case of a moving platform, would the platform be an entire map I guess?

velvet hornet
#

why would it need to be?

static cipher
#

it's just weird to me having individual tiles not aligning with their tilemap's grid I suppose

velvet hornet
#

I guess I don't understand what you mean by tilemaps "moving at all" then

static cipher
#

Oh sorry I meant changing the Transform of an individual Tile

#

it seems like it shouldn't be possible to offset a tile from it's grid -- and I guess visually it's probably not possible with the way the rendering works right?

rare bramble
#

Tiles don't have a Transform component. Even if you manually insert one, it would not work as you may expect. Tiles are batch rendered inside a chunk of multiple tiles (see the TilemapRenderSettings component). These chunks do not have a proper ECS representation but are actually tied to the top level tilemap.
The only thing you can do to move a tile is to update its TilePos component, but it will stay on the tilemap grid. In other words, you can only offset a tile by a multiple of the tile size.
For your moving platform issue I would not use a tilemap at all but a simple Sprite, which may use as source image a subset of your tileser.

velvet hornet
#

bevy_ecs_tilemap 0.16.0-rc.2 is out on crates.io now

pastel grove
velvet hornet
#

I ran the bench example against 0.12 and 0.16. these is the improvement over that release cycle timeframe.

static cipher
#

Yeah, not sure transform propagation is much of a concern anymore hehe

#

The bench example is what, 2000x2000 tiles?

velvet hornet
brisk path
static cipher
#

woah, was that with an entity per tile?

#

and only rendering a subset with the rest culled?

brisk path
static cipher
#

For 1st-party tilemaps, I'm wondering about the comparative difficulty between making ecs_tilemap upstream-able vs starting from scratch on top of new rendering features..

#

For the concerns about challenging to maintain, complex API, I wonder if that's mostly talking about it being fairly complex custom rendering code? Would it possible to simplify it today with Mesh2d/Material2d?

#

It seems like all of the shader complexity isn't avoidable if you want to support the different tile shapes.

#

I guess the complex api bit is talking about the actual user-facing api, which I think would be one of the easier bits to change if there was some consensus on what should be improved.

velvet hornet
# static cipher For 1st-party tilemaps, I'm wondering about the comparative difficulty between m...

I haven't seen any upstream interest in upstreaming ecs_tilemap and I've seen a few comments against the idea. afaict the prevailing goal at the moment is a square-tile render abstraction for tilemaps. No hex, iso, etc support. No talk about userland apis, etc. No entity-per-tile.

There's appetite from upstream for merging the simplest approach and ignoring all other features so I think that's the best course of action. Landing anything is a good first step towards any future work. Bevy is pre-1.0 so the userland API or high level features don't need to be ready-to-go on merge day 1.

So IMO the best option is to cut features until something is small enough to land. Once it lands, expand from there.

velvet hornet
# static cipher For the concerns about `challenging to maintain, complex API`, I wonder if that'...

I'm not sure I agree that the code is actually that complex compared to anything else. The hardest part about maintaining it is whenever upstream rendering apis change in larger ways, ecs_tilemap has to follow at some point and when upstream rendering changes land they often introduce bugs which make syncing with main a bit rough. but overall its not that much different than anything else.

We could absolutely refactor some of the rendering implementation but I'm hesitant to do so with the "first party tilemap implementation" kind of hanging in the air like it has for a few releases now. if we were refactoring with the goal of upstreaming sure but afaict that's not the path forward and I don't want to refactor then have to refactor again to retarget to the impending upstream abstraction.

static cipher
#

I guess I'm trying to address what it is that makes people uncomfortable with upstreaming. If it's primarily entity-per-tile, then maybe the recent improvements alleviate concerns there. If it's that it's too featureful, then maybe the create could be split up with a goal towards upstreaming the core.

velvet hornet
#

oh I don't know the answer to that. afaik it was never written down anywhere.

static cipher
#

And yeah I also don't think the code is that complex.

#

Well, not any more complex than other custom renderers, even if I myself don't fully grok it.

velvet hornet
#

I tried to ask, for example in the tilemap thread you joined, but was asked to leave bevy_ecs_tilemap out of the discussion so I took a step back.

#

which is, to be clear, fine. I'm just trying to align with upstream and put work in places it is desired. Which is why I generally think merging the small simple bit is still the right move forward

#

if for whatever reason this effort fizzles out again, then I'll revisit refactoring ecs_tilemap

static cipher
#

Oh yeah I read that, from my understanding that's just coming at the problem from two directions: building from first principles vs trying to upstream an existing solution. I sort of think that building from first principles here would likely end up re-building most of what ecs_tilemap already provides, unless there's dramatically different ideas on what the user api should look like.

#

At least that's what I was feeling when doing the chunk stuff.

velvet hornet
#

yeah I generally felt that to be true too, which is why I started PRing and accepted maintaining ecs_tilemap.

#

if we have to rebuild ecs_tilemap from scratch in upstream then that's kinda fine too though?

#

at least we'd have first party tilemaps at the end

static cipher
#

I guess I'm just not sure what the right approach is because I'm not sure what the desired end result is. That's why I think a working group would be nice, to put together a design doc for something to work towards. Then it can be determined if upstreaming makes more sense than rebuilding.

velvet hornet
#

there's a few roads that can get us to first-party tilemaps and it seems like the appetite is to do a very open source thing and land something simple then expand from there. Landing code attracts contributors, someone just has to make the first merge.

#

we'll have all of the 0.17 cycle to build on whatever lands and iterate, and people will start paying attention to it if its in upstream

static cipher
#

Yeah I'm happy to work towards that in that way too, which is why I worked on the chunking stuff -- just want to make sure I'm not stepping on toes or re-invinting a worse wheel.

#

I'm discovering just how many tilemap crates there are -- there's a ton of appetite for this

velvet hornet
#

Don't worry about me if you're worried about my toes. I'm just interested in seeing the first-party support achieved.

static cipher
#

Well not just you and StarToaster, but also all of the other people that have invested a lot more time into bevy tilemaps than I have haha

velvet hornet
#

I think upstreaming something isn't stepping on any toes. If people want to participate they will be able to through filing issues or submitting PRs

#

"hey this doesn't work for my use case" is a totally valid issue to file, for example

static cipher
#

yea true

velvet hornet
#

I think if you can land a PR everyone is going to appreciate that work

#

if we can get enough upstreamed over the next couple releases that bevy_ecs_tilemap didn't need to exist anymore I would consider that a resounding success. I think the short-term goal isn't quite that ambitious though.

static cipher
#

yeah I myself am pretty biased towards the simplest square-based entity-based tilemap approach, but I realize that's a small part of ecs_tilemap.

sick goblet
#

the chunking example seems to have a mis-type, unless i'm just mis-understanding something

#
// For this example, don't choose too large a chunk size.
const CHUNK_SIZE: UVec2 = UVec2 { x: 4, y: 4 };
// Render chunk sizes are set to 4 render chunks per user specified chunk.
const RENDER_CHUNK_SIZE: UVec2 = UVec2 {
    x: CHUNK_SIZE.x * 2,
    y: CHUNK_SIZE.y * 2,
};

shouldn't it be render chunks sizes are set to 4 user specified chunks per render chunk?

unreal condor
#

I think that the logic of the comment is that a CHUNK as 4x4 tiles, RENDER_CHUNK as 8x8 tiles. 4 chunks fitting in the area of one render chunk.

That does seem pretty odd though -- I think that a render chunk size larger than the chunk size would be meaningless? You'd end up always rendering 1 chunk per tilemap.

sick goblet
#

the source code seemed to build render chunks from the chunks

#

that is, render chunks from the tilemap, which was divided into chunks

bright flame
#

beginner question: does ecs_tilemap have any examples of iso hex grids? I have a Hexagon(RowEven) map type but the z-ordering is incorrect. Is there a way to correct the rendering order? Transforms on the tiles?

rare bramble
ocean citrus
#

This feels like a newbie question but anyways; is it possible to integrate picking with individual tiles?

velvet hornet
#

next big feature up to merge is going to be a required components implementation. picking would be nice after that.

echo saffron
#

Halo

#

Cwn somean helpa?

unreal condor
#

Feel free to just ask the question. Give as much info about your problem as you can and if someone comes around who can help they will.

true igloo
#

Hello, I am trying to integrate the bevy_ecs_tilemap with a map I built using Tiled.

I noticed an example where it supports, but I was a little lost with the "atlas feature enabled", I know it is a feature in cargo.toml but what it changes?

Btw, it seems the ldtk has a simpler code. Is it better to use ldtk instead of Tiled in the context of bevy_ecs_tilemap?

rare bramble
#

Hi! Have you tried bevy_ecs_tiled? It's a dedicated crate that basically expand on the example Tiled loader. Should handle more uses cases.

#

You can also go with Ldtk, and in that case I would recommend using bevy_ecs_ldtk. Same story but for Ldtk.

#

IIRC, atlas feature enforce usage of texture atlases to improve perfs / to allow running on lower end hardware, at the cost of preventing you to use tilesets with several images. I believe you should not need it by default. Take that with a grain of salt: I cannot check source code RN and I'm not using this feature very often

unreal condor
# true igloo Hello, I am trying to integrate the bevy_ecs_tilemap with a map I built using Ti...

It's a bit unfortunate that the examples need to have this conditional code for that feature. The idea with bevy_ecs_tilemap, anyway, is to decide if you need that feature and then rip out the conditionals in your own code.

It used to be the case that atlas was required for webgl2 builds to work properly, but I believe that's not the case anymore (wgpu has fixed some stuff, and there are some workarounds in bevy_ecs_tilemap). But there are performance, limitation, and functionality tradeoffs. If your tilemaps are already in the form of atlases, you can use the atlas feature to avoid the up-front cost of generating texture arrays at runtime. If you need mipmaps, use texture arrays. If you need > 2048 tiles in a single tilemap, maybe you want atlases.

brisk path
storm heart
#

Hello, does someone know how you can access the size of a tileset from a tile ? my aim is to change the TileTextureIndex of specific tiles to the one under it in the tileset.

true igloo
#

Hey guys, really thanks for all of you. It really helped me to make the first step.

I decided to try bevy_ecs_ldtk and it worked pretty well. I never used ldtk but it seems good too. Result:

compact coral
#

Is this always the case? For reasons I need 8x8 and 16x16?

compact coral
#

I think I spoke too soon, I deleted all 16x16 grids to see if the border bricks still worked and I'm getting the same error

compact coral
jade epoch
#

I have some tiles being drawn on layer 2, and the tilemap is also layer 2, but I'm not seeing them with a layer 2/3 camera. Id there something I'm missing?

velvet hornet
#

nothing comes to mind from that description. assuming the renderlayers are set up correctly. I haven't tried to do that recently though, so if you think its a bug definitely file an issue with a minimal reproduction.

verbal tide
#

@jade epoch If you send the full code to me I can try to strip it down

verbal tide
#

I'll get to it when I can

verbal tide
#

update: problem was user error

#

anyway

river stirrup
#

i have this weird issue

#

im trying to render an isometric staggered tilemap but it is looking like this

#

this is my config. im using the atlas from the crate -- isometric-sheet.png. but there are no examples for doing this -,- ``` let tile_size = TilemapTileSize { x: 64.0, y: 64.0 };
let grid_size = TilemapGridSize { x: 64.0, y: 64.0 };
let map_type = TilemapType::Isometric(IsoCoordSystem::Staggered);

commands.entity(tilemap_entity).insert(TilemapBundle {
    grid_size: grid_size ,
    tile_size,
    size: map_size,
    storage: tile_storage,
    texture: TilemapTexture::Single(texture_handle),
    
    map_type,
    anchor: TilemapAnchor::TopLeft,
    render_settings: TilemapRenderSettings {
            y_sort: true, 
            ..default()
    },
    ..Default::default()
});
#

why are my cubes that are 'in front' rendering 'behind ' ??????/

#

seems like render order is messed up badl

#

oh i got it !

#
 let tile_size = TilemapTileSize { x: 64.0, y: 64.0 };
    let grid_size = TilemapGridSize { x: 64.0, y: 32.0 };
    let map_type = TilemapType::Isometric(IsoCoordSystem::Staggered);

    commands.entity(tilemap_entity).insert(TilemapBundle {
        grid_size: grid_size ,
        tile_size,
        size: map_size,
        storage: tile_storage,
        texture: TilemapTexture::Single(texture_handle),
        
        map_type,
        anchor: TilemapAnchor::Center,
        render_settings: TilemapRenderSettings {

               render_chunk_size: UVec2::new(3, 1),
                 
                y_sort: true, 
                ..default()
        },
        ..Default::default()
    });

#

this fixed it -- idk why

#

ok but now how can i do multiple layers of tiles -- not just a flat plane

#

do i need a TilemapBundle for each 'layer' ?

#

3 dimensions grid

#

the only 3d example is loading a .tmx file so i cant figure out how to do it with ProcGen ..

#

ooo ok

#

got it 😄

#

idk why chunking settings fixed my issue. weird af

rare bramble
#

It fixed your issue because the y_sort setting is applied per chunk, not per tile.
By using a chunk of size 1 along y axis you achieve what you wanted.
I guess you could even increase the chunk size along x axis for better perfs

river stirrup
#

Wow okay thats quite non-idiomatic

#

But all good now

velvet hornet
rare bramble
#

Wow that was fast! Thanks for the PR!
I'm gonna start working on porting bevy_ecs_tiled.
Just a question: does switching to required components is still on the table?
I think I read somewhere you wanted to do so "during next Bevy update", but I'm not sure (and no pressure, we can live with bundles!)

velvet hornet
#

Let's try to do one rc release so the upgrade is easy for people and then put the required components change in

deep rose
#

I'm following along with the example to create a new enum type but it's not creating the file

rare bramble
#

yes, that's the idea 🙂
Did you enable the user_properties feature ?
Also, you can have a look to the book section

deep rose
#

thanks it worked

#

was a bit confused from the readme

#

it says from tiled to bevy components so I thought I had to explicitly make the properties in tiled

rare bramble
#

well, it goes both way: you first define the components you want to use in your code, then export them to use them from Tiled.

#

there is a note in the book warning you about not using types created only in Tiled

#

if that helps

deep rose
#

yeah it does thanks

abstract venture
#

well I tried to use the new bevy-0.17 branch and it does compile but dose not then render

#

good thing I still have the 0.16 version

velvet hornet
abstract venture
#

I am using the 2d template

#

let me see if adding default helps

#

or if it has it

#

im not sure

velvet hornet
#

I tried the rc without the 2d template and it works, so its gotta be a configuration issue

#

the 2d template is distributing a lockfile that prevents rc.2 from being used, make sure you update

abstract venture
#

it was both that

#

and

#

I forgot to add the plugin

#

when I was moving over

#

thank you very much

#

a 2nd time

velvet hornet
#

The rc release has been 0.17 compatible for a bit now, but I published the stable 0.17 release today if anyone was waiting for that specifically. There should be no functional changes between the two releases

tepid sedge
#

It seems like there is a bug related to scaling tilemaps. After the 64th tile, the tiles no longer display even though they are there. It is possible they do still display but in the wrong place. I did this because I wanted to use tiles as units instead of pixels, but it seems like it's ok to use pixels as units with avian physics, so I will probably just stop scaling everything. It would be cool to be able to set a pixel to unit ratio on tilemaps.

velvet hornet
#

Its possible we aren't taking the scale into consideration, but in general if everything is sized appropriately, scaling the camera perspective is the better move.

tepid sedge
#

Yes, that means I will have to use pixels as units. I have given up on my dream of tiles as units.

#

Ideally we could set pixels per unit when importing any sprites and wouldn't have to scale anything.

velvet hornet
#

I'm not sure what you mean by "wouldn't have to scale anything". It seems like that's just shifting the scale around to happen at import time

tepid sedge
#

No, it would be scaled when rendered. That is how Unity handles it.

velvet hornet
#

right, so its still scaling

tepid sedge
#

yes, I was referring to that transforms would not need to be scaled, avoiding the transform scaling issues you mentioned

#

the scaling would be done in the shader instead

velvet hornet
#

I feel like I'm not sure how that's different than scaling the camera's orthographic projection

tepid sedge
#

scaling the orthographic projection just changes the zoom. I am talking about the world units. The tilemap is at a fixed size, so I cannot change the number of units when traversing the map for example. I can just zoom to keep it in frame.

#

Or if I wanted one tilemap to be 32 pixels per tile and one to be 16 pixels per tile, I can not make them the same physical size

velvet hornet
#

is that a use case you have?

#

wildly different sized tiles that display at the same size

tepid sedge
#

a use case would be if you want to have togglable HD graphics for your game, like you want to toggle between retro and HD

velvet hornet
#

why would the size of the assets change though? Wouldn't you author the assets to be swapable?

tepid sedge
#

oh to scale the retro graphics to actual be HD, like giant pixel art? That is one way to do it. But I think specifying pixels per unit is more flexible.

#

I make crossover fan games by the way. If most of my characters are designed for 16 x 16 tiles and I want to import Simon from Super Castlevania IV who has a larger tile size, I would need to scale his transform to make his size match the other characters. If that was handled in the shader (like how Unity handles it) it is just more convenient. There are workarounds in many cases, but I am talking about developer convenience.

velvet hornet
#

yeah, I'm not against it, just trying to understand the use case and such

#

I'll want to build an example for the examples/ directory and whatnot if the feature gets added and its hard to do that without understanding

#

(or I guess in this case, the potential bug fixed)

tepid sedge
#

or if I was using the 3D physics engine, and I wanted to put some sprite characters into a 3D game, the 3D avian physics expects 1 unit to be about 1 meter. According to the resolution of my sprites, if I could set pixels per unit, I could have their size be correct to match the other 3D characters without fiddling with scaling transforms.

velvet hornet
tepid sedge
#

what do you mean by size the sprites?

velvet hornet
#

these have custom sizes, so they aren't restricted to being "the size of the image"

tepid sedge
#

Oh so the sprite already has the feature. The custom_size property. The tilemap should have something like that too.

#

Sorry I forgot Sprite had it. I hadn't worked on my game for months due to my dayjob and forgot.

velvet hornet
#

yeah no worries

tepid sedge
#

But that is the concept I am talking about. Sizing the rendering independent from the transform.

#

it would be really useful for the tilemap to have this feature as well.

#

I'll create an issue

velvet hornet
tepid sedge
velvet hornet
#

you say "I have tried scaling the tilemap" but its not clear what that means from the issue

#

thanks 😄

tepid sedge
#

Thanks. I rewrote to say "scaling the transform of the tilemap's parent".

velvet hornet
#

you might also want to check out the upstream TilemapChunk if you haven't yet

#

long-term the idea is to move more functionality upstream, so it doesn't have tile entities or whatnot yet, but might be more flexible as a low-level tool

tepid sedge
#

@velvet hornet thanks. I will take a look. Also I enjoy your this week in bevy videos. They keep me updated on the engine when I don't have time to use it.

velvet hornet
#

glad you're finding them useful!

tepid sedge
#

So if bevy_ecs_tilemap is updated to use TilemapChunk, it would probably be easy to have a custom display size

velvet hornet
velvet hornet
#

I wanted to do the work to make bevy_ecs_tilemap upstreamable awhile ago, but the consensus upstream was that a completely from-scratch implementation was desired, so now we're just kinda waiting for that to happen which puts bevy_ecs_tilemap in a weird spot

tepid sedge
#

ok thanks for the info. It seems at this current time TilemapChunk is my only option if I want to use tiles as units.

velvet hornet
#

yeah I mean, I think "tiles as units" is going to put you in a bit of a weird spot because its not like you can change the 2d world space conventions

#

so you're kinda trying to make 2d worldspace tile-sized, which is isn't.

tepid sedge
#

What do you mean? The units are just relative to the camera, so they can be anything.

velvet hornet
#

as a concrete example in bevy, the lighting calculations are based on the idea that a unit is a meter, so if you try to make a unit 100 meters, the lighting doesn't account for that

tepid sedge
#

That is precisely why I want to use tiles as units. Then my character will be 2 meters tall.

velvet hornet
#

units in 2d are pixels

#

units in 3d are meters

tepid sedge
#

that is built in to Bevy?

#

are you talking about 2D lighting?

velvet hornet
#

I'm talking about 3d lighting in that case, and generalizing that trying to change the way worldspace works invalidates assumptions generally

#

you already have "tile-space" with TilePos, etc

tepid sedge
#

So people making different resolution 2d games will have different units depending on the resolution of their art? Like a high res game will need to use higher values for moving and stuff?

#

I am used to separating rendering from the way the game works

tepid sedge
#

That is what I am talking about. Using pixels requires using high values for everything, which I was trying to avoid.

velvet hornet
#

I mean, Avian's settings don't impact the size of things on screen so I'm not entirely sure why you brought it up in the first place.

#

the size of a tilemap doesn't impact what calculations you use for physics

tepid sedge
#

It does in this case, because I cannot change the rendering size

#

I am used to other physics engines that use meters as units. That is why I mentioned the physics. Since it is not a requirement, it was just to avoid using large numbers for everything. To have more easily human thinkable jump heights and movement speeds.

#

But I am curious now why you are telling me it's a bad idea, that Bevy will not like me not using pixels as units

velvet hornet
tepid sedge
#

I know, but if I can't change the size of the tilemap, that doesn't help

#

If I use TilemapChunk, I can do whatever I want with the camera, yes

velvet hornet
#

you can do whatever you want with the camera with tilemapchunk or ecs_tilemap

tepid sedge
#

That doesn't sound right to me, but I am open to being wrong

velvet hornet
#

why wouldn't that be right?

tepid sedge
#

because I can't change the size of the tilemap if I use ecs_tilemap. Changing the camera will just zoom in or out on the map.

velvet hornet
#

what is the "size of the tilemap" if not "the size on screen"?

tepid sedge
#

yes, and moving around that map will result in moving 16 pixels per tile

#

If I scale the map, then scale the camera, I can choose how many units I move per tile

velvet hornet
#

which is why you use the TilePosition components

#

which have the tile positions

tepid sedge
#

that is the coordinate system of tiles. I am talking about the world coordinate system.

#

So based on what the units are, moving my character 5 units will be different

#

Without being able to scale the map, 5 units will move my character 5 pixels. If I can scale the map, 5 units can mean 5 tiles or whatever I want it to mean

velvet hornet
#

I'm trying to find a way to explain that you can operate in whatever system you want to, but at the end of the day it converts to Bevy's worldspace. So for example, if tilespace happened to be the "right unit size", you take the tile position and turn that into a Transform translation via some math.

#

you don't change the units Transform is using

tepid sedge
#

I don't care about the tile coordinate system though. This isn't related to that.

#

I am trying to tell you that I want to define the units bevy's world space uses.

#

Forcing 2D devs to use pixels as units is limiting in my opinion

#

bevy doesn't force it by the way, just the ecs tilemap plugin. But if it is assumed that I should use pixels as units by other parts of the engine, then that I would want to know about. But so far you told me lighting expects meters. So for me it is weird to have a different system for 2D and 3D. But I am a gamedev from a different era. I am a flash dev.

velvet hornet
#

I was around for flash too, fwiw

tepid sedge
#

I was just thinking more about it. If I ever want to add a 3D character to my game, I don't want them to be 32 units tall. It will break the lighting. So I will try and use the TilemapChunk so that I can make the world accommodate a character that is 2 units tall.

Thank you for chatting with me @velvet hornet . I think there was some misunderstanding, but I still appreciate it.

velvet hornet
tepid sedge
#

Switching to TilemapChunk fixed my problem. After the map is spawned, I iterate all of the tile entities and used their tileset_index and position to populate the tile data for each chunk, then I despawn each tile entity, and it works perfectly. I also have better performance on Mac as a side effect probably due to there being less entities.

cinder arch
#

posting this here in case anyone's interested:

I made a fork of the crate (and a fork of bevy_ecs_ldtk which uses it instead of the normal dependency) which lets you add a custom offset to each tile, via a new TileZ component.

It essentially just adds that offset over the normal z value before adding the meshes to the sort phase.

the problem it solves is that you can now have stacked tiles, such as the walls in the video, which all share the same z value (e.g. if the tiles are 2 pixels high, the bottom tile would have a TileZ of -1, the one on top would have -3, then -5, etc., setting all of their "anchors" to the bottom of the bottom tile)

it can be used in combination with the crate's y-sorting feature or you can simply have that disabled, set your tilemap's transform z to 0, and provide each tile a TileZ, doing your own custom y-sort

the big limitation is that chunks (for the relevant tilemaps) should be set to 1x1 since each chunk can have a single z

I did work on an alternate solution where chunks were grouped by z as well, letting you have chunks of multiple tiles and dividing them based on the tiles' z values but it was quite a lot of work so I ended up giving up on it and sticking to this (really minimal) fix

I also thought of turning it into a PR but it's frankly only useful for a pretty specific scenario so I don't think it's worth being upstreamed

GitHub

A tilemap rendering crate for bevy which is more ECS friendly. - PVDoriginal/bevy_ecs_tilemap

GitHub

ECS-friendly ldtk plugin for bevy, leveraging bevy_ecs_tilemap - PVDoriginal/bevy_ecs_ldtk

void nest
#

Is there any way to rotate tiles like I have north east south west directions and need to have the tiles rotated for each direction

void nest
#

Hmm I've seen that but can you rotate a tile to all the cardinal directions with tile flips?

velvet hornet
#

there's the diagonal option as well

#

it's not just x/y

warped jetty
#

in general, any two flips (mirror reflections) make a rotation

void nest
void nest
#

tilesheet*

velvet hornet
velvet hornet
#

the 0.18 stable release is published now as well

rare bramble
#

Thanks a lot for the update Chris! I'll try to release ecs_tiled tonight (CET).
Quick question though: I see the PR is still open. Do you plan to add more changes?

velvet hornet
unreal condor
#

I won’t be back at a PC until Sunday. If enabling the morph feature has some material impact on perf or resource consumption or whatever, it would suck if we were forcing it to be enabled for 2d users who are probably not using it. If not, seems fairly harmless to do what we’re doing. Trust you to make that call.

velvet hornet
# unreal condor I won’t be back at a PC until Sunday. If enabling the morph feature has some mat...

Ok, I've merged based on your previous approval.

I don't think it has any real impact, its basically part of the big material rework that's happening where things are being split up into more crates, etc. It would be nice to be able to disable it because we aren't using it but that will require adding a new default feature and letting people disable it, then not re-add it, and it would be a manual process for users to sync it up between bevy and bevy_ecs_tilemap to make sure both are either set or unset.

cold glade
#

how will i create collision for my tiles (avian2d)

#

or how does terraria do tile collision

sonic surge
#

I encountered a question while using the map_reload.rs example from bevy_ecs_tiled.
When I press the U key to completely unload the map, I noticed that the tileset images (tile0.png, tile1.png, tile2.png, etc.) are still retained in Bevy's Assets<Image> storage.
Is this expected behavior?

⁨```
info!("Unload map");

let handles: Vec<_> = maps.iter().map(|(handle, _)| handle).collect();

for handle in handles {

// This will cause the map to unload.

maps.remove(handle);

}
next_state.set(MapState::Unloaded);

velvet hornet
silent spruce
#

I noticed that a basic setup doesn't like it when you have different sized images:

Expected all provided image assets to have size TilemapTileSize { x: 64.0, y: 64.0 }, but found image with size: TilemapTileSize { x: 32.0, y: 32.0 }

What is the best way to tackle this?
Should I just independently spawn the smaller props?
Should I do a separate map and overlay it?
Is there a way to adjust things before I load them in?

I am just using this:
let map_handle: Handle<TiledMapAsset> = asset_server.load("map.tmx");
And once it gets spawned it, it errors out.

rare bramble
#

That's a limitation from bevy_ecs_tilemap. You can't have a tileset using a single image with multiple tile sizes.
To fix that, you can either: 1/ create one tileset for each tile size you need or 2/ convert your tileset so it uses an images collection instead of a single image

safe pond
sly whale
#

aka the tiles on higher y (higher up in your pics) need to be rendered before the tiles that are further down, so they can render over them instead of getting "cut off"

safe pond
#

thanks for the answer, I'd never find the example.

          // However, it applies to whole chunks, not individual tile, so we have to force the chunk
          // size to be exactly one tile along the y-axis.

ugh, haven't thought of that. But setting chunk height to 1 sounds like a performance problem, would be nice to have a proper solution.

sly whale
#

optimize when you have to

#
  1. make it work
  2. make it correct
  3. make it fast
    ^ general order of priorities