From 7ddbb4a2aaa1a87c86f7769db73e382d385b17b9 Mon Sep 17 00:00:00 2001 From: Brian Merchant Date: Tue, 25 Oct 2022 08:16:49 -0700 Subject: [PATCH] Fix how tilemap center is calculated so that it works for all map types. --- examples/accessing_tiles.rs | 10 +++++----- examples/animation.rs | 16 ++++++++++++---- examples/basic.rs | 4 +++- examples/bench.rs | 4 +++- examples/game_of_life.rs | 9 +++++---- examples/helpers/tiled.rs | 5 +++-- examples/layers.rs | 9 ++++++--- examples/ldtk/ldtk.rs | 4 ++++ examples/move_tile.rs | 4 +++- examples/random_map.rs | 5 +++-- examples/remove_tiles.rs | 4 +++- examples/spacing.rs | 11 ++++++++--- examples/texture_container.rs | 5 +++-- examples/texture_vec.rs | 5 +++-- examples/visibility.rs | 4 +++- src/helpers/geometry.rs | 29 ++++++++++++++++++----------- 16 files changed, 85 insertions(+), 43 deletions(-) diff --git a/examples/accessing_tiles.rs b/examples/accessing_tiles.rs index 5c4ea53b..3842cb5b 100644 --- a/examples/accessing_tiles.rs +++ b/examples/accessing_tiles.rs @@ -25,7 +25,7 @@ fn startup(mut commands: Commands, asset_server: Res) { // For the purposes of this example, we consider a square tile map, // where diagonals are also considered to be neighbors. - let tilemap_type = TilemapType::Square { + let map_type = TilemapType::Square { diagonal_neighbors: true, }; @@ -53,7 +53,7 @@ fn startup(mut commands: Commands, asset_server: Res) { } // We can grab a list of neighbors. - let neighbors = get_tile_neighbors(&TilePos { x: 0, y: 0 }, &tile_storage, &tilemap_type); + let neighbors = get_tile_neighbors(&TilePos { x: 0, y: 0 }, &tile_storage, &map_type); // We can access tiles using: assert!(tile_storage.get(&TilePos { x: 0, y: 0 }).is_some()); @@ -65,7 +65,7 @@ fn startup(mut commands: Commands, asset_server: Res) { color += 1; for y in (2..128).step_by(4) { // Grabbing neighbors is easy. - let neighbors = get_neighboring_pos(&TilePos { x, y }, &tilemap_size, &tilemap_type); + let neighbors = get_neighboring_pos(&TilePos { x, y }, &tilemap_size, &map_type); for pos in neighbors.into_iter() { // We can replace the tile texture component like so: commands @@ -87,10 +87,10 @@ fn startup(mut commands: Commands, asset_server: Res) { grid_size, size: tilemap_size, storage: tile_storage, - map_type: tilemap_type, + map_type, texture: TilemapTexture::Single(texture_handle), tile_size, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 0.0), ..Default::default() }) .insert(LastUpdate(0.0)) diff --git a/examples/animation.rs b/examples/animation.rs index 938fa78e..d50d4897 100644 --- a/examples/animation.rs +++ b/examples/animation.rs @@ -52,15 +52,18 @@ fn create_background(mut commands: Commands, asset_server: Res) { &mut tile_storage, ); + let map_type = TilemapType::default(); + commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { size, grid_size, + map_type, tile_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle), - transform: get_tilemap_center_transform(&size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&size, &grid_size, &map_type, 0.0), ..Default::default() }); } @@ -108,15 +111,20 @@ fn create_animated_flowers(mut commands: Commands, asset_server: Res) { let tile_size = TilemapTileSize { x: 16.0, y: 16.0 }; let grid_size = tile_size.into(); + let map_type = TilemapType::default(); commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle), tile_size, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 0.0), ..Default::default() }); } diff --git a/examples/game_of_life.rs b/examples/game_of_life.rs index 043c3344..fc373e4b 100644 --- a/examples/game_of_life.rs +++ b/examples/game_of_life.rs @@ -32,19 +32,20 @@ fn startup(mut commands: Commands, asset_server: Res) { let tile_size = TilemapTileSize { x: 16.0, y: 16.0 }; let grid_size = tile_size.into(); + let map_type = TilemapType::Square { + diagonal_neighbors: true, + }; commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle), tile_size, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 0.0), - map_type: TilemapType::Square { - diagonal_neighbors: true, - }, + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 0.0), ..Default::default() }) .insert(LastUpdate(0.0)); diff --git a/examples/helpers/tiled.rs b/examples/helpers/tiled.rs index 48cf4ebf..b57177af 100644 --- a/examples/helpers/tiled.rs +++ b/examples/helpers/tiled.rs @@ -163,7 +163,7 @@ pub fn process_loaded_maps( y: tiled_map.map.tile_height as f32, }; - let mesh_type = match tiled_map.map.orientation { + let map_type = match tiled_map.map.orientation { tiled::Orientation::Hexagonal => { TilemapType::Hexagon(HexCoordSystem::Row) } @@ -242,9 +242,10 @@ pub fn process_loaded_maps( transform: get_tilemap_center_transform( &map_size, &grid_size, + &map_type, layer.layer_index as f32, ) * Transform::from_xyz(offset_x, -offset_y, 0.0), - map_type: mesh_type, + map_type, ..Default::default() }); diff --git a/examples/layers.rs b/examples/layers.rs index 664a2c0d..73d87d5c 100644 --- a/examples/layers.rs +++ b/examples/layers.rs @@ -23,16 +23,18 @@ fn startup(mut commands: Commands, asset_server: Res) { let tile_size = TilemapTileSize { x: 16.0, y: 16.0 }; let grid_size = tile_size.into(); + let map_type = TilemapType::default(); commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle.clone()), tile_size, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 0.0), ..Default::default() }); @@ -51,12 +53,13 @@ fn startup(mut commands: Commands, asset_server: Res) { commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { - grid_size: grid_size, + grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle), tile_size: TilemapTileSize { x: 16.0, y: 16.0 }, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 1.0) + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 1.0) * Transform::from_xyz(32.0, 32.0, 0.0), ..Default::default() }); diff --git a/examples/ldtk/ldtk.rs b/examples/ldtk/ldtk.rs index 20bb7dc7..a09d402e 100644 --- a/examples/ldtk/ldtk.rs +++ b/examples/ldtk/ldtk.rs @@ -11,6 +11,7 @@ use bevy::{ asset::{AssetLoader, AssetPath, BoxedFuture, LoadContext, LoadedAsset}, prelude::*, }; +use bevy_ecs_tilemap::map::TilemapType; #[derive(Default)] pub struct LdtkPlugin; @@ -201,10 +202,12 @@ pub fn process_loaded_tile_maps( } let grid_size = tile_size.into(); + let map_type = TilemapType::default(); // Create the tilemap commands.entity(map_entity).insert_bundle(TilemapBundle { grid_size, + map_type, size, storage, texture: TilemapTexture::Single(texture), @@ -212,6 +215,7 @@ pub fn process_loaded_tile_maps( transform: get_tilemap_center_transform( &size, &grid_size, + &map_type, layer_id as f32, ), ..default() diff --git a/examples/move_tile.rs b/examples/move_tile.rs index 7a2610c0..7f259dd1 100644 --- a/examples/move_tile.rs +++ b/examples/move_tile.rs @@ -29,16 +29,18 @@ fn startup(mut commands: Commands, asset_server: Res) { let tile_size = TilemapTileSize { x: 16.0, y: 16.0 }; let grid_size = tile_size.into(); + let map_type = TilemapType::default(); commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle), tile_size, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 0.0), ..Default::default() }); } diff --git a/examples/random_map.rs b/examples/random_map.rs index 2dac52a1..a4e9898d 100644 --- a/examples/random_map.rs +++ b/examples/random_map.rs @@ -35,16 +35,17 @@ fn startup(mut commands: Commands, asset_server: Res) { let tile_size = TilemapTileSize { x: 16.0, y: 16.0 }; let grid_size = tile_size.into(); - + let map_type = TilemapType::default(); commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle), tile_size, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 0.0), ..Default::default() }); } diff --git a/examples/remove_tiles.rs b/examples/remove_tiles.rs index 7cecea5c..142e9b56 100644 --- a/examples/remove_tiles.rs +++ b/examples/remove_tiles.rs @@ -30,16 +30,18 @@ fn startup(mut commands: Commands, asset_server: Res) { let tile_size = TilemapTileSize { x: 16.0, y: 16.0 }; let grid_size = tile_size.into(); + let map_type = TilemapType::default(); commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle), tile_size, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 0.0), ..Default::default() }) .insert(LastUpdate::default()); diff --git a/examples/spacing.rs b/examples/spacing.rs index 670a270f..56a04f11 100644 --- a/examples/spacing.rs +++ b/examples/spacing.rs @@ -23,17 +23,19 @@ fn startup(mut commands: Commands, asset_server: Res) { let tile_size = TilemapTileSize { x: 16.0, y: 16.0 }; let grid_size = tile_size.into(); + let map_type = TilemapType::default(); commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle.clone()), tile_size, spacing: TilemapSpacing { x: 8.0, y: 8.0 }, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 0.0), ..Default::default() }); @@ -49,15 +51,18 @@ fn startup(mut commands: Commands, asset_server: Res) { &mut tile_storage, ); + let map_type = TilemapType::default(); + commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { - grid_size: grid_size, + grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle), tile_size: TilemapTileSize { x: 16.0, y: 16.0 }, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 1.0) + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 1.0) * Transform::from_xyz(32.0, 32.0, 0.0), ..Default::default() }); diff --git a/examples/texture_container.rs b/examples/texture_container.rs index 37e51723..7d147559 100644 --- a/examples/texture_container.rs +++ b/examples/texture_container.rs @@ -63,17 +63,18 @@ fn startup(mut commands: Commands, asset_server: Res) { let tile_size = TILE_SIZE; let grid_size = TILE_SIZE.into(); + let map_type = TilemapType::Hexagon(COORD_SYS); commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, tile_size, size: map_size, storage: tile_storage, texture: texture_vec, - map_type: TilemapType::Hexagon(COORD_SYS), - transform: get_tilemap_center_transform(&map_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&map_size, &grid_size, &map_type, 0.0), ..Default::default() }); } diff --git a/examples/texture_vec.rs b/examples/texture_vec.rs index 7839db96..5122d22d 100644 --- a/examples/texture_vec.rs +++ b/examples/texture_vec.rs @@ -65,17 +65,18 @@ fn startup(mut commands: Commands, asset_server: Res) { let tile_size = TILE_SIZE; let grid_size = TILE_SIZE.into(); + let map_type = TilemapType::Hexagon(COORD_SYS); commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, tile_size, size: map_size, storage: tile_storage, texture: texture_vec, - map_type: TilemapType::Hexagon(COORD_SYS), - transform: get_tilemap_center_transform(&map_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&map_size, &grid_size, &map_type, 0.0), ..Default::default() }); } diff --git a/examples/visibility.rs b/examples/visibility.rs index ecbd25cf..1416da45 100644 --- a/examples/visibility.rs +++ b/examples/visibility.rs @@ -30,16 +30,18 @@ fn startup(mut commands: Commands, asset_server: Res) { let tile_size = TilemapTileSize { x: 16.0, y: 16.0 }; let grid_size = tile_size.into(); + let map_type = TilemapType::default(); commands .entity(tilemap_entity) .insert_bundle(TilemapBundle { grid_size, + map_type, size: tilemap_size, storage: tile_storage, texture: TilemapTexture::Single(texture_handle), tile_size, - transform: get_tilemap_center_transform(&tilemap_size, &grid_size, 0.0), + transform: get_tilemap_center_transform(&tilemap_size, &grid_size, &map_type, 0.0), ..Default::default() }) .insert(LastUpdate::default()); diff --git a/src/helpers/geometry.rs b/src/helpers/geometry.rs index c4fe4793..8092fcc6 100644 --- a/src/helpers/geometry.rs +++ b/src/helpers/geometry.rs @@ -1,22 +1,29 @@ +use crate::map::TilemapType; +use crate::tiles::TilePos; use crate::{TilemapGridSize, TilemapSize, Transform}; use bevy::math::Vec2; -/// Calculates a [`Vec2`] position for a tilemap so that when set to this position, it shows up -/// centered on the screen. -pub fn get_tilemap_center(size: &TilemapSize, grid_size: &TilemapGridSize) -> Vec2 { - Vec2::new( - -(size.x as f32 * grid_size.x) / 2.0, - -(size.y as f32 * grid_size.y) / 2.0, - ) +/// Gets the [`Vec2`] world space position of the center tile in the tilemap. +/// +/// The center tile is defined to be the tile at +/// `TilePos { x: size.x / 2.0 as u32, y: size.y / 2.0 as u32 }`, where `size` is a `TilemapSize`. +pub fn get_tilemap_center( + size: &TilemapSize, + grid_size: &TilemapGridSize, + map_type: &TilemapType, +) -> Vec2 { + let center_pos = TilePos::new(size.x / 2.0 as u32, size.y / 2.0 as u32); + center_pos.center_in_world(grid_size, map_type) } -/// Calculates a [`Transform`] for a tilemap so that when set to this position, it shows up -/// centered on the screen. +/// Calculates a [`Transform`] for a tilemap that places it so that the center tile is at +/// `(0.0, 0.0, 0.0)` in world space. pub fn get_tilemap_center_transform( size: &TilemapSize, grid_size: &TilemapGridSize, + map_type: &TilemapType, z: f32, ) -> Transform { - let center = get_tilemap_center(size, grid_size); - Transform::from_xyz(center.x, center.y, z) + let center = get_tilemap_center(size, grid_size, map_type); + Transform::from_xyz(-center.x, -center.y, z) }