From 36480d3de4e320241f9a85f6a069bbf597f73522 Mon Sep 17 00:00:00 2001 From: JohnTheCoolingFan Date: Tue, 11 Apr 2023 22:14:12 +0300 Subject: [PATCH 1/8] Added hex_radius_chunk example --- examples/hex_radius_chunk.rs | 448 +++++++++++++++++++++++++++++++++++ 1 file changed, 448 insertions(+) create mode 100644 examples/hex_radius_chunk.rs diff --git a/examples/hex_radius_chunk.rs b/examples/hex_radius_chunk.rs new file mode 100644 index 00000000..0686810a --- /dev/null +++ b/examples/hex_radius_chunk.rs @@ -0,0 +1,448 @@ +use bevy::{math::Vec4Swizzles, prelude::*}; +use bevy_ecs_tilemap::{helpers::hex_grid::offset::*, prelude::*}; +mod helpers; +use helpers::camera::movement as camera_movement; + +const CHUNK_MAP_SIDE_LENGTH_X: u32 = 4; +const CHUNK_MAP_SIDE_LENGTH_Y: u32 = 4; + +const CHUNKS_X: i32 = 2; +const CHUNKS_Y: i32 = 2; + +const TILE_SIZE_HEX_ROW: TilemapTileSize = TilemapTileSize { x: 50.0, y: 58.0 }; +const TILE_SIZE_HEX_COL: TilemapTileSize = TilemapTileSize { x: 58.0, y: 50.0 }; +const GRID_SIZE_HEX_ROW: TilemapGridSize = TilemapGridSize { x: 50.0, y: 58.0 }; +const GRID_SIZE_HEX_COL: TilemapGridSize = TilemapGridSize { x: 58.0, y: 50.0 }; + +#[derive(Deref, Resource)] +pub struct TileHandleHexRow(Handle); + +#[derive(Deref, Resource)] +pub struct TileHandleHexCol(Handle); +#[derive(Deref, Resource)] +pub struct FontHandle(Handle); + +impl FromWorld for TileHandleHexCol { + fn from_world(world: &mut World) -> Self { + let asset_server = world.resource::(); + Self(asset_server.load("bw-tile-hex-col.png")) + } +} +impl FromWorld for TileHandleHexRow { + fn from_world(world: &mut World) -> Self { + let asset_server = world.resource::(); + Self(asset_server.load("bw-tile-hex-row.png")) + } +} +impl FromWorld for FontHandle { + fn from_world(world: &mut World) -> Self { + let asset_server = world.resource::(); + Self(asset_server.load("fonts/FiraSans-Bold.ttf")) + } +} + +#[derive(Deref, Component, Clone, Copy)] +pub struct ChunkPos(IVec2); + +fn chunk_in_world_position(pos: IVec2, map_type: TilemapType) -> Vec3 { + let tile_size = match map_type { + TilemapType::Hexagon(HexCoordSystem::RowEven) + | TilemapType::Hexagon(HexCoordSystem::RowOdd) => TILE_SIZE_HEX_ROW, + TilemapType::Hexagon(HexCoordSystem::ColumnEven) + | TilemapType::Hexagon(HexCoordSystem::ColumnOdd) => TILE_SIZE_HEX_COL, + _ => unreachable!(), + }; + let grid_size = match map_type { + TilemapType::Hexagon(HexCoordSystem::RowEven) + | TilemapType::Hexagon(HexCoordSystem::RowOdd) => GRID_SIZE_HEX_ROW, + TilemapType::Hexagon(HexCoordSystem::ColumnEven) + | TilemapType::Hexagon(HexCoordSystem::ColumnOdd) => GRID_SIZE_HEX_COL, + _ => unreachable!(), + }; + Vec3::new( + tile_size.x * CHUNK_MAP_SIDE_LENGTH_X as f32 * pos.x as f32, + TilePos { + x: 0, + y: CHUNK_MAP_SIDE_LENGTH_Y, + } + .center_in_world(&grid_size, &map_type) + .y * pos.y as f32, + 0.0, + ) +} + +fn hex_pos_from_tile_pos( + tile_pos: &TilePos, + grid_size: &TilemapGridSize, + map_type: &TilemapType, + map_transform: &Transform, +) -> IVec2 { + let tile_translation = + *map_transform * tile_pos.center_in_world(grid_size, map_type).extend(0.0); + match map_type { + TilemapType::Hexagon(HexCoordSystem::RowEven) => { + let pos = RowEvenPos::from_world_pos(&tile_translation.truncate(), grid_size); + IVec2 { x: pos.q, y: pos.r } + } + TilemapType::Hexagon(HexCoordSystem::RowOdd) => { + let pos = RowOddPos::from_world_pos(&tile_translation.truncate(), grid_size); + IVec2 { x: pos.q, y: pos.r } + } + TilemapType::Hexagon(HexCoordSystem::ColumnEven) => { + let pos = ColEvenPos::from_world_pos(&tile_translation.truncate(), grid_size); + IVec2 { x: pos.q, y: pos.r } + } + TilemapType::Hexagon(HexCoordSystem::ColumnOdd) => { + let pos = ColOddPos::from_world_pos(&tile_translation.truncate(), grid_size); + IVec2 { x: pos.q, y: pos.r } + } + _ => unreachable!(), + } +} + +fn hex_neighbors_radius( + hex_pos: IVec2, + radius: u32, + grid_size: &TilemapGridSize, + map_type: &TilemapType, +) -> Vec { + let neighbors = generate_hexagon( + match map_type { + TilemapType::Hexagon(HexCoordSystem::RowEven) => RowEvenPos { + q: hex_pos.x, + r: hex_pos.y, + } + .into(), + TilemapType::Hexagon(HexCoordSystem::RowOdd) => RowOddPos { + q: hex_pos.x, + r: hex_pos.y, + } + .into(), + TilemapType::Hexagon(HexCoordSystem::ColumnEven) => ColEvenPos { + q: hex_pos.x, + r: hex_pos.y, + } + .into(), + TilemapType::Hexagon(HexCoordSystem::ColumnOdd) => ColOddPos { + q: hex_pos.x, + r: hex_pos.y, + } + .into(), + _ => unreachable!(), + }, + radius, + ); + neighbors + .into_iter() + .map(|axial_pos| match map_type { + TilemapType::Hexagon(HexCoordSystem::RowEven) => { + let pos = RowEvenPos::from(axial_pos); + IVec2 { x: pos.q, y: pos.r } + } + TilemapType::Hexagon(HexCoordSystem::RowOdd) => { + let pos = RowOddPos::from(axial_pos); + IVec2 { x: pos.q, y: pos.r } + } + TilemapType::Hexagon(HexCoordSystem::ColumnEven) => { + let pos = ColEvenPos::from(axial_pos); + IVec2 { x: pos.q, y: pos.r } + } + TilemapType::Hexagon(HexCoordSystem::ColumnOdd) => { + let pos = ColOddPos::from(axial_pos); + IVec2 { x: pos.q, y: pos.r } + } + _ => unreachable!(), + }) + .collect() +} + +fn hex_neighbors_radius_from_tile_pos( + tile_pos: &TilePos, + grid_size: &TilemapGridSize, + map_type: &TilemapType, + map_transform: &Transform, + radius: u32, +) -> Vec { + let hex_pos = hex_pos_from_tile_pos(tile_pos, grid_size, map_type, map_transform); + hex_neighbors_radius(hex_pos, radius, grid_size, map_type) +} + +fn spawn_chunks(mut commands: Commands, tile_handle_hex_row: Res) { + commands.spawn(Camera2dBundle::default()); + + let map_size = TilemapSize { + x: CHUNK_MAP_SIDE_LENGTH_X, + y: CHUNK_MAP_SIDE_LENGTH_Y, + }; + + let tile_size = TILE_SIZE_HEX_ROW; + let grid_size = GRID_SIZE_HEX_ROW; + let map_type = TilemapType::Hexagon(HexCoordSystem::RowEven); + + // Makes it so chunks spawn around the world center + let lower_bound_x = -(CHUNKS_X / 2); + let lower_bound_y = -(CHUNKS_Y / 2); + for chunk_x in lower_bound_x..(CHUNKS_X + lower_bound_x) { + for chunk_y in lower_bound_y..(CHUNKS_Y + lower_bound_y) { + let chunk_pos = ChunkPos(IVec2 { + x: chunk_x, + y: chunk_y, + }); + + let mut tile_storage = TileStorage::empty(map_size); + let tilemap_entity = commands.spawn_empty().id(); + let tilemap_id = TilemapId(tilemap_entity); + + fill_tilemap( + TileTextureIndex(0), + map_size, + tilemap_id, + &mut commands, + &mut tile_storage, + ); + + commands + .entity(tilemap_entity) + .insert(TilemapBundle { + grid_size, + size: map_size, + storage: tile_storage, + texture: TilemapTexture::Single(tile_handle_hex_row.clone()), + tile_size, + map_type, + transform: Transform::from_translation(chunk_in_world_position( + *chunk_pos, map_type, + )), + ..Default::default() + }) + .insert(chunk_pos); + } + } +} + +#[derive(Component)] +struct TileLabel(Entity); + +fn spawn_tile_labels( + mut commands: Commands, + tilemap_q: Query<(&Transform, &TilemapType, &TilemapGridSize, &TileStorage)>, + tile_q: Query<&TilePos>, + font_handle: Res, +) { + let text_style = TextStyle { + font: font_handle.clone(), + font_size: 20.0, + color: Color::BLACK, + }; + let text_alignment = TextAlignment::Center; + for (map_transform, map_type, grid_size, tilemap_storage) in tilemap_q.iter() { + for tile_entity in tilemap_storage.iter().flatten() { + let tile_pos = tile_q.get(*tile_entity).unwrap(); + let tile_center = tile_pos.center_in_world(grid_size, map_type).extend(1.0); + let transform = *map_transform * Transform::from_translation(tile_center); + + let hex_pos = hex_pos_from_tile_pos(tile_pos, grid_size, map_type, map_transform); + + let label_entity = commands + .spawn(Text2dBundle { + text: Text::from_section( + format!("{}, {}", hex_pos.x, hex_pos.y), + text_style.clone(), + ) + .with_alignment(text_alignment), + transform, + ..default() + }) + .id(); + commands + .entity(*tile_entity) + .insert(TileLabel(label_entity)); + } + } +} + +#[derive(Component)] +struct Hovered; + +#[derive(Resource)] +pub struct CursorPos(Vec2); +impl Default for CursorPos { + fn default() -> Self { + // Initialize the cursor pos at some far away place. It will get updated + // correctly when the cursor moves. + Self(Vec2::new(-1000.0, -1000.0)) + } +} + +pub fn update_cursor_pos( + camera_q: Query<(&GlobalTransform, &Camera)>, + mut cursor_moved_events: EventReader, + mut cursor_pos: ResMut, +) { + for cursor_moved in cursor_moved_events.iter() { + // To get the mouse's world position, we have to transform its window position by + // any transforms on the camera. This is done by projecting the cursor position into + // camera space (world space). + for (cam_t, cam) in camera_q.iter() { + if let Some(pos) = cam.viewport_to_world_2d(cam_t, cursor_moved.position) { + *cursor_pos = CursorPos(pos); + } + } + } +} + +// This is where we check whicch tile the cursor is hovered over. +fn hover_highlight_tile_label( + mut commands: Commands, + cursor_pos: Res, + tilemap_q: Query<( + &TilemapSize, + &TilemapGridSize, + &TilemapType, + &TileStorage, + &Transform, + )>, + highlighted_tiles_q: Query>, + tile_label_q: Query<&TileLabel>, + mut text_q: Query<&mut Text>, +) { + // Un-highlight any previously highlighted tile labels. + for highlighted_tile_entity in highlighted_tiles_q.iter() { + if let Ok(label) = tile_label_q.get(highlighted_tile_entity) { + if let Ok(mut tile_text) = text_q.get_mut(label.0) { + for mut section in tile_text.sections.iter_mut() { + section.style.color = Color::BLACK; + } + commands.entity(highlighted_tile_entity).remove::(); + } + } + } + + for (map_size, grid_size, map_type, tile_storage, map_transform) in tilemap_q.iter() { + let cursor_pos = cursor_pos.0; + let cursor_pos_in_map_pos = { + let cursor_pos = Vec4::from((cursor_pos, 0.0, 1.0)); + let cursor_in_map_pos = map_transform.compute_matrix().inverse() * cursor_pos; + cursor_in_map_pos.xy() + }; + if let Some(tile_pos) = + TilePos::from_world_pos(&cursor_pos_in_map_pos, map_size, grid_size, map_type) + { + if let Some(tile_entity) = tile_storage.get(&tile_pos) { + if let Ok(label) = tile_label_q.get(tile_entity) { + if let Ok(mut tile_text) = text_q.get_mut(label.0) { + for mut section in tile_text.sections.iter_mut() { + section.style.color = Color::RED; + } + commands.entity(tile_entity).insert(Hovered); + } + } + } + } + } +} + +#[derive(Component)] +struct NeighborHighlight; + +// Highlight neighbors of a tile in a radius +fn highlight_neighbor_labels( + mut commands: Commands, + tilemap_query: Query<( + &TilemapType, + &TilemapSize, + &TilemapGridSize, + &TileStorage, + &Transform, + )>, + highlighted_tiles_q: Query>, + hovered_tiles_q: Query<(Entity, &TilePos), With>, + tiles_q: Query<&TilePos, Without>, + tile_label_q: Query<&TileLabel>, + mut text_q: Query<&mut Text>, +) { + for highlighted_tile_entity in highlighted_tiles_q.iter() { + if let Ok(label) = tile_label_q.get(highlighted_tile_entity) { + if let Ok(mut tile_text) = text_q.get_mut(label.0) { + for mut section in tile_text.sections.iter_mut() { + section.style.color = Color::BLACK; + } + commands + .entity(highlighted_tile_entity) + .remove::(); + } + } + } + + let mut neighbors: Option> = None; + + for (map_type, map_size, grid_size, tile_storage, map_t) in tilemap_query.iter() { + for (hovered_tile_entity, hovered_tile_pos) in hovered_tiles_q.iter() { + if let Some(ent) = tile_storage.checked_get(hovered_tile_pos) { + if ent == hovered_tile_entity { + neighbors = Some(hex_neighbors_radius_from_tile_pos( + hovered_tile_pos, + grid_size, + map_type, + map_t, + 2, + )); + } + } + } + } + + if let Some(neighbors) = neighbors { + for (map_type, map_size, grid_size, tile_storage, map_t) in tilemap_query.iter() { + for opt_tile_entity in tile_storage.iter() { + if let Some(tile_entity) = opt_tile_entity { + if let Ok(tile_pos) = tiles_q.get(*tile_entity) { + let tile_hex_pos = + hex_pos_from_tile_pos(tile_pos, grid_size, map_type, map_t); + if neighbors.contains(&tile_hex_pos) { + if let Ok(label) = tile_label_q.get(*tile_entity) { + if let Ok(mut tile_text) = text_q.get_mut(label.0) { + for mut section in tile_text.sections.iter_mut() { + section.style.color = Color::BLUE; + } + commands.entity(*tile_entity).insert(NeighborHighlight); + } + } + } + } + } + } + } + } +} + +#[derive(SystemSet, Clone, Copy, Hash, PartialEq, Eq, Debug)] +pub struct SpawnChunksSet; + +fn main() { + App::new() + .add_plugins( + DefaultPlugins + .set(WindowPlugin { + primary_window: Some(Window { + title: String::from( + "Hexagon radius - Hover over a tile to higlight tiles in a radius, use up and down arrow to change radius", + ), + ..Default::default() + }), + ..default() + }) + .set(ImagePlugin::default_nearest()), + ) + .add_plugin(TilemapPlugin) + .init_resource::() + .init_resource::() + .init_resource::() + .init_resource::() + .add_startup_systems((spawn_chunks, apply_system_buffers).chain().in_set(SpawnChunksSet)) + .add_startup_system(spawn_tile_labels.after(SpawnChunksSet)) + .add_systems((camera_movement, update_cursor_pos).chain().in_base_set(CoreSet::First)) + .add_system(hover_highlight_tile_label) + .add_system(highlight_neighbor_labels.after(hover_highlight_tile_label)) + .run(); +} From 8542ba71fd2740bde6c54de15a61f06249e37f17 Mon Sep 17 00:00:00 2001 From: JohnTheCoolingFan Date: Tue, 11 Apr 2023 22:15:00 +0300 Subject: [PATCH 2/8] Clean up example from unused stuff --- examples/hex_radius_chunk.rs | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/examples/hex_radius_chunk.rs b/examples/hex_radius_chunk.rs index 0686810a..0322ce91 100644 --- a/examples/hex_radius_chunk.rs +++ b/examples/hex_radius_chunk.rs @@ -100,12 +100,7 @@ fn hex_pos_from_tile_pos( } } -fn hex_neighbors_radius( - hex_pos: IVec2, - radius: u32, - grid_size: &TilemapGridSize, - map_type: &TilemapType, -) -> Vec { +fn hex_neighbors_radius(hex_pos: IVec2, radius: u32, map_type: &TilemapType) -> Vec { let neighbors = generate_hexagon( match map_type { TilemapType::Hexagon(HexCoordSystem::RowEven) => RowEvenPos { @@ -164,7 +159,7 @@ fn hex_neighbors_radius_from_tile_pos( radius: u32, ) -> Vec { let hex_pos = hex_pos_from_tile_pos(tile_pos, grid_size, map_type, map_transform); - hex_neighbors_radius(hex_pos, radius, grid_size, map_type) + hex_neighbors_radius(hex_pos, radius, map_type) } fn spawn_chunks(mut commands: Commands, tile_handle_hex_row: Res) { @@ -348,13 +343,7 @@ struct NeighborHighlight; // Highlight neighbors of a tile in a radius fn highlight_neighbor_labels( mut commands: Commands, - tilemap_query: Query<( - &TilemapType, - &TilemapSize, - &TilemapGridSize, - &TileStorage, - &Transform, - )>, + tilemap_query: Query<(&TilemapType, &TilemapGridSize, &TileStorage, &Transform)>, highlighted_tiles_q: Query>, hovered_tiles_q: Query<(Entity, &TilePos), With>, tiles_q: Query<&TilePos, Without>, @@ -376,7 +365,7 @@ fn highlight_neighbor_labels( let mut neighbors: Option> = None; - for (map_type, map_size, grid_size, tile_storage, map_t) in tilemap_query.iter() { + for (map_type, grid_size, tile_storage, map_t) in tilemap_query.iter() { for (hovered_tile_entity, hovered_tile_pos) in hovered_tiles_q.iter() { if let Some(ent) = tile_storage.checked_get(hovered_tile_pos) { if ent == hovered_tile_entity { @@ -393,7 +382,7 @@ fn highlight_neighbor_labels( } if let Some(neighbors) = neighbors { - for (map_type, map_size, grid_size, tile_storage, map_t) in tilemap_query.iter() { + for (map_type, grid_size, tile_storage, map_t) in tilemap_query.iter() { for opt_tile_entity in tile_storage.iter() { if let Some(tile_entity) = opt_tile_entity { if let Ok(tile_pos) = tiles_q.get(*tile_entity) { From 7d7ca6968457fab3a14199cc72a7173a0ca3839b Mon Sep 17 00:00:00 2001 From: JohnTheCoolingFan Date: Tue, 11 Apr 2023 22:15:49 +0300 Subject: [PATCH 3/8] Rename example --- examples/{hex_radius_chunk.rs => hex_neighbors_radius_chunks.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{hex_radius_chunk.rs => hex_neighbors_radius_chunks.rs} (100%) diff --git a/examples/hex_radius_chunk.rs b/examples/hex_neighbors_radius_chunks.rs similarity index 100% rename from examples/hex_radius_chunk.rs rename to examples/hex_neighbors_radius_chunks.rs From 9c9c68a57a7892b998775455a78d7e82ec1c1636 Mon Sep 17 00:00:00 2001 From: JohnTheCoolingFan Date: Tue, 11 Apr 2023 22:24:21 +0300 Subject: [PATCH 4/8] Add changing radius --- examples/hex_neighbors_radius_chunks.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/examples/hex_neighbors_radius_chunks.rs b/examples/hex_neighbors_radius_chunks.rs index 0322ce91..4de49952 100644 --- a/examples/hex_neighbors_radius_chunks.rs +++ b/examples/hex_neighbors_radius_chunks.rs @@ -14,6 +14,8 @@ const TILE_SIZE_HEX_COL: TilemapTileSize = TilemapTileSize { x: 58.0, y: 50.0 }; const GRID_SIZE_HEX_ROW: TilemapGridSize = TilemapGridSize { x: 50.0, y: 58.0 }; const GRID_SIZE_HEX_COL: TilemapGridSize = TilemapGridSize { x: 58.0, y: 50.0 }; +const MAX_RADIUS: u32 = 6; + #[derive(Deref, Resource)] pub struct TileHandleHexRow(Handle); @@ -337,6 +339,22 @@ fn hover_highlight_tile_label( } } +#[derive(Deref, Resource)] +struct HighlightRadius(u32); +impl Default for HighlightRadius { + fn default() -> Self { + Self(2) + } +} + +fn update_radius(mut radius: ResMut, keyboard_input: Res>) { + if keyboard_input.just_pressed(KeyCode::Up) { + radius.0 = std::cmp::min(MAX_RADIUS, radius.0 + 1); + } else if keyboard_input.just_pressed(KeyCode::Down) { + radius.0 = std::cmp::max(1, radius.0 - 1); + } +} + #[derive(Component)] struct NeighborHighlight; @@ -349,6 +367,7 @@ fn highlight_neighbor_labels( tiles_q: Query<&TilePos, Without>, tile_label_q: Query<&TileLabel>, mut text_q: Query<&mut Text>, + radius: Res, ) { for highlighted_tile_entity in highlighted_tiles_q.iter() { if let Ok(label) = tile_label_q.get(highlighted_tile_entity) { @@ -374,7 +393,7 @@ fn highlight_neighbor_labels( grid_size, map_type, map_t, - 2, + **radius, )); } } @@ -425,6 +444,7 @@ fn main() { ) .add_plugin(TilemapPlugin) .init_resource::() + .init_resource::() .init_resource::() .init_resource::() .init_resource::() @@ -432,6 +452,7 @@ fn main() { .add_startup_system(spawn_tile_labels.after(SpawnChunksSet)) .add_systems((camera_movement, update_cursor_pos).chain().in_base_set(CoreSet::First)) .add_system(hover_highlight_tile_label) - .add_system(highlight_neighbor_labels.after(hover_highlight_tile_label)) + .add_system(update_radius.after(hover_highlight_tile_label)) + .add_system(highlight_neighbor_labels.after(update_radius)) .run(); } From 98999d59d4d811500a26979fa74924799c8287de Mon Sep 17 00:00:00 2001 From: JohnTheCoolingFan Date: Tue, 11 Apr 2023 22:49:43 +0300 Subject: [PATCH 5/8] Switching map type --- examples/hex_neighbors_radius_chunks.rs | 109 +++++++++++++++++++++--- 1 file changed, 98 insertions(+), 11 deletions(-) diff --git a/examples/hex_neighbors_radius_chunks.rs b/examples/hex_neighbors_radius_chunks.rs index 4de49952..b950d3db 100644 --- a/examples/hex_neighbors_radius_chunks.rs +++ b/examples/hex_neighbors_radius_chunks.rs @@ -61,16 +61,39 @@ fn chunk_in_world_position(pos: IVec2, map_type: TilemapType) -> Vec3 { | TilemapType::Hexagon(HexCoordSystem::ColumnOdd) => GRID_SIZE_HEX_COL, _ => unreachable!(), }; - Vec3::new( - tile_size.x * CHUNK_MAP_SIDE_LENGTH_X as f32 * pos.x as f32, - TilePos { - x: 0, - y: CHUNK_MAP_SIDE_LENGTH_Y, - } - .center_in_world(&grid_size, &map_type) - .y * pos.y as f32, - 0.0, - ) + if matches!( + map_type, + TilemapType::Hexagon(HexCoordSystem::RowEven) + | TilemapType::Hexagon(HexCoordSystem::RowOdd) + ) { + Vec3::new( + tile_size.x * CHUNK_MAP_SIDE_LENGTH_X as f32 * pos.x as f32, + TilePos { + x: 0, + y: CHUNK_MAP_SIDE_LENGTH_Y, + } + .center_in_world(&grid_size, &map_type) + .y * pos.y as f32, + 0.0, + ) + } else if matches!( + map_type, + TilemapType::Hexagon(HexCoordSystem::ColumnEven) + | TilemapType::Hexagon(HexCoordSystem::ColumnOdd) + ) { + Vec3::new( + TilePos { + x: CHUNK_MAP_SIDE_LENGTH_X, + y: 0, + } + .center_in_world(&grid_size, &map_type) + .x * pos.x as f32, + tile_size.y * CHUNK_MAP_SIDE_LENGTH_Y as f32 * pos.y as f32, + 0.0, + ) + } else { + unreachable!() + } } fn hex_pos_from_tile_pos( @@ -217,6 +240,69 @@ fn spawn_chunks(mut commands: Commands, tile_handle_hex_row: Res, + keyboard_input: Res>, + tile_label_q: Query<(&TileLabel, &TilePos), Without>, + mut transform_q: Query<&mut Transform, Without>, + tile_handle_hex_row: Res, + tile_handle_hex_col: Res, +) { + if keyboard_input.just_pressed(KeyCode::Space) { + for ( + mut map_transform, + map_size, + mut map_type, + mut grid_size, + mut map_texture, + mut tile_size, + chunk_pos, + ) in tilemap_query.iter_mut() + { + match map_type.as_ref() { + TilemapType::Hexagon(HexCoordSystem::RowEven) => { + *map_type = TilemapType::Hexagon(HexCoordSystem::RowOdd) + } + TilemapType::Hexagon(HexCoordSystem::RowOdd) => { + *map_type = TilemapType::Hexagon(HexCoordSystem::ColumnEven); + *map_texture = TilemapTexture::Single((*tile_handle_hex_col).clone()); + *tile_size = TILE_SIZE_HEX_COL; + *grid_size = GRID_SIZE_HEX_COL; + } + TilemapType::Hexagon(HexCoordSystem::ColumnEven) => { + *map_type = TilemapType::Hexagon(HexCoordSystem::ColumnOdd); + } + TilemapType::Hexagon(HexCoordSystem::ColumnOdd) => { + *map_type = TilemapType::Hexagon(HexCoordSystem::RowEven); + *map_texture = TilemapTexture::Single((*tile_handle_hex_row).clone()); + *tile_size = TILE_SIZE_HEX_ROW; + *grid_size = GRID_SIZE_HEX_ROW; + } + _ => unreachable!(), + } + + *map_transform = + Transform::from_translation(chunk_in_world_position(**chunk_pos, *map_type)); + + for (label, tile_pos) in tile_label_q.iter() { + if let Ok(mut tile_label_transform) = transform_q.get_mut(label.0) { + let tile_center = tile_pos.center_in_world(&grid_size, &map_type).extend(0.0); + *tile_label_transform = + *map_transform * Transform::from_translation(tile_center); + } + } + } + } +} + #[derive(Component)] struct TileLabel(Entity); @@ -451,7 +537,8 @@ fn main() { .add_startup_systems((spawn_chunks, apply_system_buffers).chain().in_set(SpawnChunksSet)) .add_startup_system(spawn_tile_labels.after(SpawnChunksSet)) .add_systems((camera_movement, update_cursor_pos).chain().in_base_set(CoreSet::First)) - .add_system(hover_highlight_tile_label) + .add_system(swap_map_type) + .add_system(hover_highlight_tile_label.after(swap_map_type)) .add_system(update_radius.after(hover_highlight_tile_label)) .add_system(highlight_neighbor_labels.after(update_radius)) .run(); From 3f168ae2ea58be6e2c7afe067ce1bfb7f7ca2513 Mon Sep 17 00:00:00 2001 From: JohnTheCoolingFan Date: Tue, 11 Apr 2023 22:53:47 +0300 Subject: [PATCH 6/8] Fixed label display --- examples/hex_neighbors_radius_chunks.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/examples/hex_neighbors_radius_chunks.rs b/examples/hex_neighbors_radius_chunks.rs index b950d3db..1ff1755d 100644 --- a/examples/hex_neighbors_radius_chunks.rs +++ b/examples/hex_neighbors_radius_chunks.rs @@ -248,10 +248,11 @@ fn swap_map_type( &mut TilemapGridSize, &mut TilemapTexture, &mut TilemapTileSize, + &TileStorage, &ChunkPos, )>, keyboard_input: Res>, - tile_label_q: Query<(&TileLabel, &TilePos), Without>, + tile_label_q: Query<(Entity, &TileLabel, &TilePos), Without>, mut transform_q: Query<&mut Transform, Without>, tile_handle_hex_row: Res, tile_handle_hex_col: Res, @@ -264,6 +265,7 @@ fn swap_map_type( mut grid_size, mut map_texture, mut tile_size, + tile_storage, chunk_pos, ) in tilemap_query.iter_mut() { @@ -292,11 +294,16 @@ fn swap_map_type( *map_transform = Transform::from_translation(chunk_in_world_position(**chunk_pos, *map_type)); - for (label, tile_pos) in tile_label_q.iter() { + for (tile_entity, label, tile_pos) in tile_label_q.iter() { if let Ok(mut tile_label_transform) = transform_q.get_mut(label.0) { - let tile_center = tile_pos.center_in_world(&grid_size, &map_type).extend(0.0); - *tile_label_transform = - *map_transform * Transform::from_translation(tile_center); + if let Some(ent) = tile_storage.checked_get(tile_pos) { + if ent == tile_entity { + let tile_center = + tile_pos.center_in_world(&grid_size, &map_type).extend(1.0); + *tile_label_transform = + *map_transform * Transform::from_translation(tile_center); + } + } } } } From 5842f6c5434494a02292193e848bef3280e380fa Mon Sep 17 00:00:00 2001 From: JohnTheCoolingFan Date: Tue, 11 Apr 2023 22:54:10 +0300 Subject: [PATCH 7/8] Removed unused query --- examples/hex_neighbors_radius_chunks.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/hex_neighbors_radius_chunks.rs b/examples/hex_neighbors_radius_chunks.rs index 1ff1755d..3ba7d888 100644 --- a/examples/hex_neighbors_radius_chunks.rs +++ b/examples/hex_neighbors_radius_chunks.rs @@ -243,7 +243,6 @@ fn spawn_chunks(mut commands: Commands, tile_handle_hex_row: Res Date: Tue, 11 Apr 2023 22:57:56 +0300 Subject: [PATCH 8/8] Update tile coordinate labels on map type update --- examples/hex_neighbors_radius_chunks.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/hex_neighbors_radius_chunks.rs b/examples/hex_neighbors_radius_chunks.rs index 3ba7d888..a6211bfb 100644 --- a/examples/hex_neighbors_radius_chunks.rs +++ b/examples/hex_neighbors_radius_chunks.rs @@ -252,7 +252,7 @@ fn swap_map_type( )>, keyboard_input: Res>, tile_label_q: Query<(Entity, &TileLabel, &TilePos), Without>, - mut transform_q: Query<&mut Transform, Without>, + mut transform_q: Query<(&mut Transform, &mut Text), Without>, tile_handle_hex_row: Res, tile_handle_hex_col: Res, ) { @@ -293,13 +293,23 @@ fn swap_map_type( Transform::from_translation(chunk_in_world_position(**chunk_pos, *map_type)); for (tile_entity, label, tile_pos) in tile_label_q.iter() { - if let Ok(mut tile_label_transform) = transform_q.get_mut(label.0) { + if let Ok((mut tile_label_transform, mut tile_label_text)) = + transform_q.get_mut(label.0) + { if let Some(ent) = tile_storage.checked_get(tile_pos) { if ent == tile_entity { let tile_center = tile_pos.center_in_world(&grid_size, &map_type).extend(1.0); *tile_label_transform = *map_transform * Transform::from_translation(tile_center); + let hex_pos = hex_pos_from_tile_pos( + tile_pos, + &grid_size, + &map_type, + &map_transform, + ); + tile_label_text.sections.get_mut(0).unwrap().value = + format!("{}, {}", hex_pos.x, hex_pos.y); } } }