Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example for spawning and despawning tilemaps #578

Closed
rparrett opened this issue Dec 6, 2024 · 0 comments · Fixed by #585
Closed

Add example for spawning and despawning tilemaps #578

rparrett opened this issue Dec 6, 2024 · 0 comments · Fixed by #585

Comments

@rparrett
Copy link
Collaborator

rparrett commented Dec 6, 2024

This is something I'd like to be able to test easily in repo when upgrading Bevy or hacking on the renderer.

I attempted to add it in my Bevy 0.15 migration PR, but it was somehow causing "headless CI" to fail. Could be related to having to add a bevy_ui dependency somehow.

We should figure out why that's happening and add it back at some point.

edit: Oops, the issue was the I just forgot to specify the required render feature for the new example.

Expand code
//! Example showing tilemap despawning.

use bevy::{input::common_conditions::input_just_pressed, prelude::*};
use bevy_ecs_tilemap::prelude::*;

mod helpers;

fn startup(mut commands: Commands) {
    commands.spawn(Camera2d);
    commands.spawn((
        Text::new("space: spawn tilemap\nesc: despawn tilemap"),
        Node {
            position_type: PositionType::Absolute,
            top: Val::Px(12.0),
            left: Val::Px(12.0),
            ..default()
        },
    ));
}

fn spawn_map(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    maps: Query<(), With<TileStorage>>,
) {
    let num_maps = maps.iter().len();

    let texture_handle: Handle<Image> = asset_server.load("tiles.png");

    let map_size = TilemapSize { x: 32, y: 32 };

    let tilemap_entity = commands.spawn_empty().id();

    let mut tile_storage = TileStorage::empty(map_size);

    // Spawn the elements of the tilemap.
    // Alternatively, you can use helpers::filling::fill_tilemap.
    for x in 0..map_size.x {
        for y in 0..map_size.y {
            let tile_pos = TilePos { x, y };
            let tile_entity = commands
                .spawn(TileBundle {
                    position: tile_pos,
                    tilemap_id: TilemapId(tilemap_entity),
                    color: TileColor(
                        Hsla::hsl(0., 0.9, 0.8)
                            .rotate_hue(num_maps as f32 * 19.)
                            .into(),
                    ),
                    texture_index: TileTextureIndex(5),
                    ..default()
                })
                .id();
            tile_storage.set(&tile_pos, tile_entity);
        }
    }

    let tile_size = TilemapTileSize { x: 16.0, y: 16.0 };
    let grid_size = tile_size.into();
    let map_type = TilemapType::default();

    let offset = Vec3::splat(num_maps as f32 * tile_size.x / 2.);
    let mut transform = get_tilemap_center_transform(&map_size, &grid_size, &map_type, 0.0);
    transform.translation += offset;

    commands.entity(tilemap_entity).insert(TilemapBundle {
        grid_size,
        map_type,
        size: map_size,
        storage: tile_storage,
        texture: TilemapTexture::Single(texture_handle),
        tile_size,
        transform,
        ..default()
    });
}

fn despawn_map(mut commands: Commands, mut maps: Query<(Entity, &mut TileStorage, &Transform)>) {
    let Some((tilemap_entity, mut tile_storage, _)) = maps
        .iter_mut()
        .sort_by::<&Transform>(|a, b| b.translation.z.partial_cmp(&a.translation.z).unwrap())
        .next()
    else {
        return;
    };

    commands.entity(tilemap_entity).despawn_recursive();

    // Really feels like the bevy_ecs_tilemap should be doing this for us.
    for maybe_entity in tile_storage.iter_mut() {
        if let Some(entity) = maybe_entity.take() {
            commands.entity(entity).despawn_recursive();
        }
    }
}

fn main() {
    App::new()
        .add_plugins(
            DefaultPlugins
                .set(WindowPlugin {
                    primary_window: Some(Window {
                        title: String::from("Despawn Tilemap Example"),
                        ..default()
                    }),
                    ..default()
                })
                .set(ImagePlugin::default_nearest()),
        )
        .add_plugins(TilemapPlugin)
        .add_systems(Startup, startup)
        .add_systems(Update, helpers::camera::movement)
        .add_systems(Update, spawn_map.run_if(input_just_pressed(KeyCode::Space)))
        .add_systems(
            Update,
            despawn_map.run_if(input_just_pressed(KeyCode::Escape)),
        )
        .run();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant