From 912ee376c6d8e4a84f4fea1696f963b5cb801183 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Sat, 14 Mar 2026 19:55:53 -0400 Subject: [PATCH] refactoring hex coords --- Cargo.lock | 17 +- Cargo.toml | 1 + engine/world_generation/Cargo.toml | 1 + engine/world_generation/src/consts.rs | 3 +- .../src/generators/chunk_colliders.rs | 27 +- .../src/generators/mesh_generator.rs | 94 ++++-- .../src/generators/packed_mesh_generator.rs | 29 +- engine/world_generation/src/heightmap.rs | 80 +++-- engine/world_generation/src/hex_utils.rs | 312 ------------------ engine/world_generation/src/lib.rs | 3 +- engine/world_generation/src/map/biome_map.rs | 112 ++++--- engine/world_generation/src/map/chunk.rs | 79 ----- engine/world_generation/src/map/config.rs | 20 +- engine/world_generation/src/map/map.rs | 173 ++++++---- engine/world_generation/src/map/map_utils.rs | 4 +- engine/world_generation/src/map/mesh_chunk.rs | 4 +- engine/world_generation/src/map/mod.rs | 7 +- engine/world_generation/src/prelude.rs | 1 - game/buildings/Cargo.toml | 1 + game/buildings/src/build_queue.rs | 15 +- game/buildings/src/buildings_map.rs | 65 ++-- game/buildings/src/footprint.rs | 4 +- game/main/Cargo.toml | 2 + game/main/src/camera_system/camera_plugin.rs | 2 +- game/main/src/camera_system/components.rs | 2 +- game/main/src/map_rendering/map_init.rs | 3 +- game/main/src/utlis/chunk_utils.rs | 4 +- game/main/src/utlis/tile_selection_plugin.rs | 4 +- game/shared/Cargo.toml | 1 + game/shared/src/coords.rs | 6 +- game/shared/src/events.rs | 8 +- game/shared/src/resources.rs | 11 +- game/units/Cargo.toml | 1 + game/units/src/components.rs | 5 +- game/units/src/nav_data.rs | 57 ++-- game/units/src/units_plugin.rs | 135 +++++--- 36 files changed, 595 insertions(+), 698 deletions(-) delete mode 100644 engine/world_generation/src/hex_utils.rs delete mode 100644 engine/world_generation/src/map/chunk.rs diff --git a/Cargo.lock b/Cargo.lock index accaebc..db46056 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,9 +445,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bevy" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec689b5a79452b6f777b889bbff22d3216b82a8d2ab7814d4a0eb571e9938d97" +checksum = "1fd310426290cec560221f9750c2f4484be4a8eeea7de3483c423329b465c40e" dependencies = [ "bevy_internal", "tracing", @@ -1993,6 +1993,7 @@ dependencies = [ "bevy", "bevy_asset_loader", "bevy_rapier3d", + "hex", "ron 0.12.0", "serde", "serde_json", @@ -3493,6 +3494,14 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "hex" +version = "0.1.0" +dependencies = [ + "bevy", + "serde", +] + [[package]] name = "hexasphere" version = "16.0.0" @@ -4933,6 +4942,7 @@ dependencies = [ "bevy_asset_loader", "bevy_rapier3d", "buildings", + "hex", "image", "noise", "rayon", @@ -5714,6 +5724,7 @@ name = "shared" version = "0.1.0" dependencies = [ "bevy", + "hex", "serde", "world_generation", ] @@ -6321,6 +6332,7 @@ dependencies = [ "bevy", "bevy_asset_loader", "bevy_rapier3d", + "hex", "ordered-float", "pathfinding", "quadtree_rs", @@ -7515,6 +7527,7 @@ dependencies = [ "bevy", "bevy-inspector-egui", "bevy_asset_loader", + "hex", "image", "noise", "num 0.4.3", diff --git a/Cargo.toml b/Cargo.toml index d7b478f..92ae420 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ members = [ "engine/world_generation", "engine/asset_loader", "engine/data", + "engine/hex", ] # Enable a small amount of optimization in debug mode diff --git a/engine/world_generation/Cargo.toml b/engine/world_generation/Cargo.toml index 2295ccc..fe6e10e 100644 --- a/engine/world_generation/Cargo.toml +++ b/engine/world_generation/Cargo.toml @@ -20,6 +20,7 @@ bevy_asset_loader = { version = "0.25.0", features = [ ron = "0.12.0" image = "0.25.9" num = "0.4.3" +hex = { path = "../hex" } [features] tracing = ["bevy/trace_tracy"] diff --git a/engine/world_generation/src/consts.rs b/engine/world_generation/src/consts.rs index 557cebc..b0999e3 100644 --- a/engine/world_generation/src/consts.rs +++ b/engine/world_generation/src/consts.rs @@ -1,6 +1,7 @@ use bevy::{mesh::MeshVertexAttribute, prelude::*, render::render_resource::VertexFormat}; +use hex::{INNER_RADIUS, OUTER_RADIUS}; -use crate::hex_utils::{INNER_RADIUS, OUTER_RADIUS}; +// use crate::hex_utils::{INNER_RADIUS, OUTER_RADIUS}; pub const TEX_MULTI: Vec2 = Vec2::new(1000., 1.); diff --git a/engine/world_generation/src/generators/chunk_colliders.rs b/engine/world_generation/src/generators/chunk_colliders.rs index 9beeb68..a8220eb 100644 --- a/engine/world_generation/src/generators/chunk_colliders.rs +++ b/engine/world_generation/src/generators/chunk_colliders.rs @@ -1,18 +1,22 @@ -use crate::{hex_utils::*, prelude::*}; +use crate::prelude::*; #[cfg(feature = "tracing")] use bevy::log::*; use bevy::prelude::*; +use hex::prelude::*; const CHUNK_TOTAL: usize = Chunk::SIZE * Chunk::SIZE; -pub fn generate_chunk_collider(chunk: &MeshChunkData) -> (Vec, Vec<[u32; 3]>) { +pub fn generate_chunk_collider(chunk: &MeshChunkData) -> (Vec, Vec<[u32; 3]>) +{ #[cfg(feature = "tracing")] let span = info_span!("generate_chunk_collider").entered(); let vertex_count: usize = CHUNK_TOTAL * 6; let mut verts = Vec::with_capacity(vertex_count); let mut indices = Vec::with_capacity(vertex_count); - for z in 0..Chunk::SIZE { - for x in 0..Chunk::SIZE { + for z in 0..Chunk::SIZE + { + for x in 0..Chunk::SIZE + { let height = chunk.heights[x + z * Chunk::SIZE]; let coord = HexCoord::from_grid_pos(x, z); let neighbors = chunk.get_neighbors(&coord); @@ -24,9 +28,11 @@ pub fn generate_chunk_collider(chunk: &MeshChunkData) -> (Vec, Vec<[u32; 3 return (verts, indices); } -fn create_tile_collider(pos: Vec3, verts: &mut Vec, indices: &mut Vec<[u32; 3]>, neighbors: &[f32; 6]) { +fn create_tile_collider(pos: Vec3, verts: &mut Vec, indices: &mut Vec<[u32; 3]>, neighbors: &[f32; 6]) +{ let idx = verts.len() as u32; - for i in 0..6 { + for i in 0..6 + { let p = pos + HEX_CORNERS[i]; verts.push(p); } @@ -37,9 +43,11 @@ fn create_tile_collider(pos: Vec3, verts: &mut Vec, indices: &mut Vec<[u32 indices.push([idx + 2, idx + 4, idx + 5]); indices.push([idx + 2, idx + 3, idx + 4]); - for i in 0..neighbors.len() { + for i in 0..neighbors.len() + { let n_height = neighbors[i]; - if n_height < pos.y { + if n_height < pos.y + { create_tile_wall_collider( idx, Vec3::new(pos.x, n_height.min(pos.y - OUTER_RADIUS / 2.), pos.z), @@ -51,7 +59,8 @@ fn create_tile_collider(pos: Vec3, verts: &mut Vec, indices: &mut Vec<[u32 } } -fn create_tile_wall_collider(idx: u32, pos: Vec3, dir: usize, verts: &mut Vec, indices: &mut Vec<[u32; 3]>) { +fn create_tile_wall_collider(idx: u32, pos: Vec3, dir: usize, verts: &mut Vec, indices: &mut Vec<[u32; 3]>) +{ let idx2 = verts.len() as u32; verts.push(pos + HEX_CORNERS[(dir) % 6]); diff --git a/engine/world_generation/src/generators/mesh_generator.rs b/engine/world_generation/src/generators/mesh_generator.rs index 64baf02..321545c 100644 --- a/engine/world_generation/src/generators/mesh_generator.rs +++ b/engine/world_generation/src/generators/mesh_generator.rs @@ -1,12 +1,13 @@ -use crate::hex_utils::HexCoord; -use crate::{hex_utils::offset3d_to_world, prelude::*}; +use crate::prelude::*; use bevy::asset::RenderAssetUsages; #[cfg(feature = "tracing")] use bevy::log::*; use bevy::mesh::{Indices, PrimitiveTopology}; use bevy::prelude::*; +use hex::prelude::*; -pub fn generate_chunk_mesh(chunk: &MeshChunkData) -> Mesh { +pub fn generate_chunk_mesh(chunk: &MeshChunkData) -> Mesh +{ #[cfg(feature = "tracing")] let span = info_span!("generate_chunk_mesh").entered(); @@ -16,8 +17,10 @@ pub fn generate_chunk_mesh(chunk: &MeshChunkData) -> Mesh { let mut indices = Vec::with_capacity(vertex_count); let mut normals = Vec::with_capacity(vertex_count); - for z in 0..Chunk::SIZE { - for x in 0..Chunk::SIZE { + for z in 0..Chunk::SIZE + { + for x in 0..Chunk::SIZE + { let idx = x + z * Chunk::SIZE; let height = chunk.heights[idx]; let off_pos = Vec3::new(x as f32, height, z as f32); @@ -59,20 +62,23 @@ fn create_tile( normals: &mut Vec, texture_index: u32, side_texture_index: u32, -) { +) +{ let uv_offset = Vec2::splat(0.5); let tex_off = Vec2::new(texture_index as f32, 0.); let side_tex_off = Vec2::new(side_texture_index as f32, 0.); let idx = verts.len() as u32; - for i in 0..6 { + for i in 0..6 + { let p = pos + HEX_CORNERS[i]; verts.push(p); let uv = (HEX_CORNERS[i].xz() / 2.) + uv_offset; uvs.push((uv / TEX_MULTI) + tex_off); normals.push(Vec3::Y); } - for i in 0..3 { + for i in 0..3 + { let off = i * 2; indices.push(off + idx); indices.push(((off + 1) % 6) + idx); @@ -82,15 +88,19 @@ fn create_tile( indices.push(idx + 2); indices.push(idx + 4); - for i in 0..neighbors.len() { + for i in 0..neighbors.len() + { let n_height = neighbors[i]; - if n_height < pos.y { + if n_height < pos.y + { create_tile_wall(pos, i, n_height, verts, uvs, indices, normals, side_tex_off); } } } -pub fn generate_chunk_water_mesh(chunk: &MeshChunkData, sealevel: f32, map_width: usize, map_height: usize) -> Mesh { +#[allow(unused)] +pub fn generate_chunk_water_mesh(chunk: &MeshChunkData, sealevel: f32, map_width: usize, map_height: usize) -> Mesh +{ #[cfg(feature = "tracing")] let _gen_mesh = info_span!("Generate Water Surface Mesh").entered(); let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 7; @@ -99,11 +109,14 @@ pub fn generate_chunk_water_mesh(chunk: &MeshChunkData, sealevel: f32, map_width let mut indices = Vec::with_capacity(vertex_count); let mut normals = Vec::with_capacity(vertex_count); - for z in 0..Chunk::SIZE { - for x in 0..Chunk::SIZE { + for z in 0..Chunk::SIZE + { + for x in 0..Chunk::SIZE + { let idx = x + z * Chunk::SIZE; let height = chunk.heights[idx]; - if height > sealevel { + if height > sealevel + { continue; } let off_pos = Vec3::new(x as f32, sealevel, z as f32); @@ -143,8 +156,10 @@ fn create_tile_water_surface( uvs: &mut Vec, indices: &mut Vec, normals: &mut Vec, -) { - if !neighbor_has_land { +) +{ + if !neighbor_has_land + { crate_tile_water_inner_surface(pos, dist_to_land, neighbors, verts, uvs, indices, normals); return; } @@ -159,23 +174,29 @@ fn crate_tile_water_inner_surface( uvs: &mut Vec, indices: &mut Vec, normals: &mut Vec, -) { +) +{ //todo: share verts let idx = verts.len() as u32; - for i in 0..6 { + for i in 0..6 + { let p = pos + HEX_CORNERS[i]; verts.push(p); let n1 = if let Some(v) = neighbors[i].1 { v } else { dist_to_land }; - let n2 = if let Some(v) = neighbors[(i + 5) % 6].1 { + let n2 = if let Some(v) = neighbors[(i + 5) % 6].1 + { v - } else { + } + else + { dist_to_land }; let d = (n1 + n2 + dist_to_land) / 3.0; uvs.push(Vec2::new(0.0, d.remap(0., 4., 1.0, 0.0))); normals.push(Vec3::Y); } - for i in 0..3 { + for i in 0..3 + { let off = i * 2; indices.push(off + idx); indices.push(((off + 1) % 6) + idx); @@ -194,13 +215,15 @@ fn crate_tile_water_shore_surface( uvs: &mut Vec, indices: &mut Vec, normals: &mut Vec, -) { +) +{ let idx = verts.len() as u32; //todo: only use triangle fan when on shoreline verts.push(pos); uvs.push(Vec2::new(0.0, dist_to_land.remap(0., 4., 1.0, 0.0))); normals.push(Vec3::Y); - for i in 0..12 { + for i in 0..12 + { let p = pos + WATER_HEX_CORNERS[i]; verts.push(p); let ni = i / 2; @@ -208,16 +231,21 @@ fn crate_tile_water_shore_surface( let nn = neighbors[(ni + 5) % 6]; let mut uv = Vec2::new(0.0, dist_to_land.remap(0., 4., 1.0, 0.0)); - if nn.0 > pos.y || n.0 > pos.y { + if nn.0 > pos.y || n.0 > pos.y + { uv.x = 1.0; } - if ni * 2 != i { - if n.0 <= pos.y { + if ni * 2 != i + { + if n.0 <= pos.y + { uv.x = 0.0; } let d = if let Some(v) = n.1 { v } else { dist_to_land }; uv.y = ((d + dist_to_land) / 2.0).remap(0., 4., 1.0, 0.0); - } else { + } + else + { let d = if let Some(v) = n.1 { v } else { dist_to_land }; let d2 = if let Some(v) = nn.1 { v } else { dist_to_land }; uv.y = ((d + d2 + dist_to_land) / 3.0).remap(0., 4., 1.0, 0.0); @@ -241,7 +269,8 @@ fn create_tile_wall( indices: &mut Vec, normals: &mut Vec, tex_off: Vec2, -) { +) +{ let p1 = HEX_CORNERS[(dir) % 6] + pos; let p2 = HEX_CORNERS[(dir + 1) % 6] + pos; let p3 = Vec3::new(p1.x, height, p1.z); @@ -275,12 +304,14 @@ fn create_tile_wall( } #[cfg(test)] -mod tests { +mod tests +{ use super::*; #[test] - fn generate_tile_wall() { + fn generate_tile_wall() + { let mut verts = Vec::new(); let mut uvs = Vec::new(); let mut normals = Vec::new(); @@ -307,7 +338,8 @@ mod tests { } #[test] - fn generate_tile() { + fn generate_tile() + { let mut verts = Vec::new(); let mut uvs = Vec::new(); let mut normals = Vec::new(); diff --git a/engine/world_generation/src/generators/packed_mesh_generator.rs b/engine/world_generation/src/generators/packed_mesh_generator.rs index c7d27fe..476752c 100644 --- a/engine/world_generation/src/generators/packed_mesh_generator.rs +++ b/engine/world_generation/src/generators/packed_mesh_generator.rs @@ -1,19 +1,22 @@ -use crate::hex_utils::HexCoord; use crate::prelude::*; use bevy::asset::RenderAssetUsages; use bevy::{ mesh::{Indices, PrimitiveTopology}, prelude::*, }; +use hex::prelude::*; -pub fn generate_packed_chunk_mesh(chunk: &MeshChunkData) -> Mesh { +pub fn generate_packed_chunk_mesh(chunk: &MeshChunkData) -> Mesh +{ let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6; let mut packed_data = Vec::with_capacity(vertex_count); let mut indices = Vec::with_capacity(vertex_count); let mut heights = Vec::with_capacity(vertex_count); - for z in 0..Chunk::SIZE { - for x in 0..Chunk::SIZE { + for z in 0..Chunk::SIZE + { + for x in 0..Chunk::SIZE + { let idx = x + z * Chunk::SIZE; let height = chunk.heights[idx]; let coord = HexCoord::from_grid_pos(x, z); @@ -51,12 +54,14 @@ fn create_packed_tile( heights: &mut Vec, texture_index: u32, side_texture_index: u32, -) { +) +{ let idx = packed_data.len() as u32; packed_data.push(pack_vertex_data(offset, 0, texture_index)); heights.push(height); - for i in 0..6 { + for i in 0..6 + { packed_data.push(pack_vertex_data(offset, i + 1, texture_index)); indices.push(idx); indices.push(idx + 1 + i as u32); @@ -64,9 +69,11 @@ fn create_packed_tile( heights.push(height); } - for i in 0..neighbors.len() { + for i in 0..neighbors.len() + { let n_height = neighbors[i]; - if n_height < height { + if n_height < height + { create_packed_tile_wall( offset, height, @@ -90,7 +97,8 @@ fn create_packed_tile_wall( indices: &mut Vec, heights: &mut Vec, side_texture_index: u32, -) { +) +{ let idx = packed_data.len() as u32; let side_2 = ((side + 1) % 6) + 1; @@ -113,7 +121,8 @@ fn create_packed_tile_wall( indices.push(idx + 3); } -fn pack_vertex_data(offset: UVec2, vert: usize, tex: u32) -> u32 { +fn pack_vertex_data(offset: UVec2, vert: usize, tex: u32) -> u32 +{ //6 + 6 bits offset //4 bits vert //12 bits texture diff --git a/engine/world_generation/src/heightmap.rs b/engine/world_generation/src/heightmap.rs index a09b2ac..9ebf36e 100644 --- a/engine/world_generation/src/heightmap.rs +++ b/engine/world_generation/src/heightmap.rs @@ -3,6 +3,7 @@ use core::f32; use bevy::math::{IVec2, UVec2}; use bevy::prelude::{FloatExt, Vec2}; use bevy::utils::default; +use hex::prelude::*; use noise::{NoiseFn, Simplex, SuperSimplex}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; @@ -10,7 +11,8 @@ use crate::biome_painter::BiomePainter; use crate::map::biome_map::{BiomeChunk, BiomeData, BiomeMap}; use crate::prelude::*; -pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> (Map, BiomeMap) { +pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> (Map, BiomeMap) +{ let biomes = generate_biomes(cfg, seed, painter); let biomes_borrow = &biomes; // let mut chunks: Vec = Vec::with_capacity(cfg.size.length_squared() as usize); @@ -25,11 +27,14 @@ pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePain .collect(); let mut min = f32::MAX; let mut max = f32::MIN; - for chunk in &chunks { - if chunk.min_level < min { + for chunk in &chunks + { + if chunk.min_level < min + { min = chunk.min_level; } - if chunk.max_level > max { + if chunk.max_level > max + { max = chunk.max_level; } } @@ -48,7 +53,8 @@ pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePain ); } -pub fn generate_biomes(cfg: &GenerationConfig, seed: u32, biome_painter: &BiomePainter) -> BiomeMap { +pub fn generate_biomes(cfg: &GenerationConfig, seed: u32, biome_painter: &BiomePainter) -> BiomeMap +{ let mut map = BiomeMap::new(cfg.size, biome_painter.biomes.len()); map.chunks = (0..cfg.size.y) .into_par_iter() @@ -68,7 +74,8 @@ pub fn generate_biome_chunk( cfg: &GenerationConfig, seed: u32, biome_painter: &BiomePainter, -) -> BiomeChunk { +) -> BiomeChunk +{ let mut chunk = BiomeChunk { offset: UVec2::new(chunk_x as u32, chunk_y as u32), data: [BiomeData::default(); Chunk::AREA], @@ -78,8 +85,10 @@ pub fn generate_biome_chunk( let noise_t = Simplex::new(seed + 2); let noise_c = Simplex::new(seed + 3); - for z in 0..Chunk::SIZE { - for x in 0..Chunk::SIZE { + for z in 0..Chunk::SIZE + { + for x in 0..Chunk::SIZE + { let moisture = sample_point( x as f64 + chunk_x as f64 * Chunk::SIZE as f64, z as f64 + chunk_y as f64 * Chunk::SIZE as f64, @@ -123,14 +132,16 @@ pub fn generate_biome_chunk( return chunk; } -pub fn generate_noise_map(size: UVec2, seed: u32, cfg: &NoiseConfig, border_size: f32) -> Vec { +pub fn generate_noise_map(size: UVec2, seed: u32, cfg: &NoiseConfig, border_size: f32) -> Vec +{ let noise = SuperSimplex::new(seed); let data: Vec<_> = (0..(size.y as usize * Chunk::SIZE)) .into_par_iter() .flat_map(|y| { let mut row = Vec::with_capacity(size.x as usize * Chunk::SIZE); - for x in 0..row.capacity() { + for x in 0..row.capacity() + { row.push(sample_point( x as f64, y as f64, @@ -154,21 +165,26 @@ pub fn generate_chunk( seed: u32, biome_chunk: &BiomeChunk, biome_painter: &BiomePainter, -) -> Chunk { +) -> Chunk +{ let mut result: [f32; Chunk::SIZE * Chunk::SIZE] = [0.; Chunk::AREA]; let mut data = [BiomeData::default(); Chunk::AREA]; let mut biome_ids = [0; Chunk::AREA]; let noise = Simplex::new(seed); let mut min = f32::MAX; let mut max = f32::MIN; - for z in 0..Chunk::SIZE { - for x in 0..Chunk::SIZE { + for z in 0..Chunk::SIZE + { + for x in 0..Chunk::SIZE + { let biome_data = biome_chunk.get_biome_data(x, z); let biome_blend = biome_chunk.get_biome(x, z); let mut sample = 0.; - for i in 0..biome_blend.len() { + for i in 0..biome_blend.len() + { let blend = biome_blend[i]; - if blend == 0. { + if blend == 0. + { continue; } let biome = &biome_painter.biomes[i]; @@ -185,10 +201,12 @@ pub fn generate_chunk( let idx = x + z * Chunk::SIZE; biome_ids[idx] = biome_chunk.get_biome_id_dithered(x, z, &noise, cfg.biome_dither); result[idx] = sample; - if sample > max { + if sample > max + { max = sample; } - if sample < min { + if sample < min + { min = sample; } data[idx] = biome_data.clone(); @@ -212,23 +230,29 @@ fn sample_point( size: Vec2, border_size: f32, border_value: f32, -) -> f32 { +) -> f32 +{ let x_s = x / cfg.scale; let z_s = z / cfg.scale; let mut elevation: f64 = 0.; - for i in 0..cfg.layers.len() { + for i in 0..cfg.layers.len() + { let value: f64; let layer = &cfg.layers[i]; - if layer.is_rigid { + if layer.is_rigid + { value = sample_rigid(x_s, z_s, layer, noise); - } else { + } + else + { value = sample_simple(x_s, z_s, layer, noise); } elevation += value; } - if border_size == 0.0 { + if border_size == 0.0 + { return elevation as f32; } @@ -243,12 +267,14 @@ fn sample_point( return border_value.lerp(elevation as f32, d); } -fn sample_simple(x: f64, z: f64, cfg: &GeneratorLayer, noise: &impl NoiseFn) -> f64 { +fn sample_simple(x: f64, z: f64, cfg: &GeneratorLayer, noise: &impl NoiseFn) -> f64 +{ let mut freq: f64 = cfg.base_roughness; let mut amp: f64 = 1.; let mut value = 0.; - for _ in 0..cfg.layers { + for _ in 0..cfg.layers + { let v = noise.get([x * freq, z * freq]); value += (v + 1.) * 0.5 * amp; freq *= cfg.roughness; @@ -257,12 +283,14 @@ fn sample_simple(x: f64, z: f64, cfg: &GeneratorLayer, noise: &impl NoiseFn) -> f64 { +fn sample_rigid(x: f64, z: f64, cfg: &GeneratorLayer, noise: &impl NoiseFn) -> f64 +{ let mut freq: f64 = cfg.base_roughness; let mut amp: f64 = 1.; let mut value = 0.; let mut weight = 1.; - for _ in 0..cfg.layers { + for _ in 0..cfg.layers + { let mut v = 1. - noise.get([x * freq, z * freq]).abs(); v *= v; v *= weight; diff --git a/engine/world_generation/src/hex_utils.rs b/engine/world_generation/src/hex_utils.rs deleted file mode 100644 index 510a60f..0000000 --- a/engine/world_generation/src/hex_utils.rs +++ /dev/null @@ -1,312 +0,0 @@ -use std::fmt::Display; - -use crate::prelude::Chunk; -use bevy::prelude::*; -use serde::{Deserialize, Serialize}; - -pub const OUTER_RADIUS: f32 = 1.; -pub const INNER_RADIUS: f32 = OUTER_RADIUS * (SQRT_3 / 2.); -pub const SHORT_DIAGONAL: f32 = 1. * SQRT_3; -pub const LONG_DIAGONAL: f32 = 2. * OUTER_RADIUS; -const SQRT_3: f32 = 1.7320508076; - -pub fn offset3d_to_world(offset: Vec3) -> Vec3 { - let x = (offset.x + (offset.z * 0.5) - (offset.z / 2.).floor()) * (INNER_RADIUS * 2.); - return Vec3::new(x, offset.y, offset.z * OUTER_RADIUS * 1.5); -} - -pub fn offset_to_world(offset: IVec2, height: f32) -> Vec3 { - let off = offset.as_vec2(); - let x = (off.x + (off.y * 0.5) - (off.y / 2.).floor()) * (INNER_RADIUS * 2.); - return Vec3::new(x, height, off.y * OUTER_RADIUS * 1.5); -} - -pub fn offset_to_hex(offset: IVec2) -> IVec3 { - let mut v = IVec3 { - x: offset.x - (offset.y / 2), - y: offset.y, - z: 0, - }; - v.z = -v.x - v.y; - return v; -} - -pub fn offset_to_index(offset: IVec2, width: usize) -> usize { - return offset.x as usize + offset.y as usize * width; -} - -pub fn snap_to_hex_grid(world_pos: Vec3) -> Vec3 { - return offset_to_world(world_to_offset_pos(world_pos), world_pos.y); -} - -pub fn world_to_offset_pos(world_pos: Vec3) -> IVec2 { - let offset = world_pos.z / (OUTER_RADIUS * 3.); - let x = (world_pos.x / (INNER_RADIUS * 2.)) - offset; - let z = -world_pos.x - offset; - - let ix = x.round() as i32; - let iz = z.round() as i32; - let ox = ix + iz / 2; - let oz = iz; - return IVec2::new(ox, oz); -} - -pub fn tile_to_world_distance(dist: u32) -> f32 { - return dist as f32 * (2. * INNER_RADIUS); -} - -pub fn get_tile_count_in_range(radius: usize) -> usize { - return 1 + 3 * (radius + 1) * radius; -} - -#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash)] -pub struct HexCoord { - pub hex: IVec3, -} - -impl Display for HexCoord { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("HexCoord{}", self.hex)) - } -} - -impl HexCoord { - pub const DIRECTIONS: [IVec3; 6] = [ - IVec3::new(0, 1, -1), - IVec3::new(1, 0, -1), - IVec3::new(1, -1, 0), - IVec3::new(0, -1, 1), - IVec3::new(-1, 0, 1), - IVec3::new(-1, 1, 0), - ]; - - pub const ZERO: HexCoord = HexCoord { hex: IVec3::ZERO }; - - pub fn new(x: i32, z: i32) -> Self { - return HexCoord { - hex: IVec3::new(x, z, -x - z), - }; - } - - pub fn from_hex(hex: IVec2) -> Self { - return HexCoord { - hex: IVec3::new(hex.x, hex.y, -hex.x - hex.y), - }; - } - pub fn from_grid_pos(x: usize, z: usize) -> Self { - return HexCoord::new(x as i32 - (z as i32 / 2), z as i32); - } - pub fn from_offset(offset_pos: IVec2) -> Self { - return HexCoord { - hex: offset_to_hex(offset_pos), - }; - } - - pub fn from_world_pos(world_pos: Vec3) -> Self { - let offset = world_pos.z / (OUTER_RADIUS * 3.); - let mut x = world_pos.x / (INNER_RADIUS * 2.); - let mut z = -x; - z -= offset; - x -= offset; - - let i_x = x.round() as i32; - let i_z = (-x - z).round() as i32; - let offset_pos = IVec2::new(i_x + i_z / 2, i_z); - - return Self::from_offset(offset_pos); - } - - pub fn is_in_bounds(&self, map_height: usize, map_width: usize) -> bool { - let off = self.to_offset(); - if off.x < 0 || off.y < 0 { - return false; - } - - if off.x >= map_width as i32 || off.y >= map_height as i32 { - return false; - } - - return true; - } - - pub fn is_on_chunk_edge(&self) -> bool { - let offset = self.to_offset().rem_euclid(IVec2::splat(Chunk::SIZE as i32)); - let e = (Chunk::SIZE - 1) as i32; - return offset.x == 0 || offset.y == 0 || offset.x == e || offset.y == e; - } - - pub fn to_chunk_pos(&self) -> IVec2 { - let off = self.to_offset(); - - return IVec2 { - x: (off.x as f32 / Chunk::SIZE as f32).floor() as i32, - y: (off.y as f32 / Chunk::SIZE as f32).floor() as i32, - }; - } - - /// Converts this coordinate to it's chunk local equivalent - pub fn to_chunk(&self) -> HexCoord { - let c_pos = self.to_chunk_pos(); - let off = self.to_offset(); - return HexCoord::from_offset( - ( - off.x - (c_pos.x * Chunk::SIZE as i32), - off.y - (c_pos.y * Chunk::SIZE as i32), - ) - .into(), - ); - } - - pub fn to_world(&self, height: f32) -> Vec3 { - return offset_to_world(self.to_offset(), height); - } - - pub fn to_offset(&self) -> IVec2 { - return IVec2::new(self.hex.x + (self.hex.y / 2), self.hex.y); - } - - /// Convert the current coordiante to an index - pub fn to_index(&self, width: usize) -> usize { - return ((self.hex.x + self.hex.y * width as i32) + (self.hex.y / 2)) as usize; - } - - /// Gets the index of this coord in the chunk array. - /// - /// [`width`] is in number of chunks - pub fn to_chunk_index(&self, width: usize) -> usize { - let pos = self.to_chunk_pos(); - return (pos.x + pos.y * width as i32) as usize; - } - - /// Gets the index of this tile in the chunk - pub fn to_chunk_local_index(&self) -> usize { - return self.to_chunk().to_index(Chunk::SIZE); - } - - pub fn distance(&self, other: &HexCoord) -> i32 { - return (self.hex.x - other.hex.x).abs() + (self.hex.y - other.hex.y).abs() + (self.hex.z - other.hex.z).abs(); - } - - pub fn rotate_around(&self, center: &HexCoord, angle: i32) -> HexCoord { - if self == center || angle == 0 { - return self.clone(); - } - - let mut a = angle % 6; - let mut pc = self.hex - center.hex; - - if a > 0 { - for _ in 0..a { - pc = Self::slide_right(pc); - } - } else { - a = a.abs(); - for _ in 0..a { - pc = Self::slide_left(pc); - } - } - return HexCoord::from_hex(pc.xy() + center.hex.xy()); - } - - fn slide_left(hex: IVec3) -> IVec3 { - return (hex * -1).yzx(); - } - - fn slide_right(hex: IVec3) -> IVec3 { - return (hex * -1).zxy(); - } - - pub fn scale(&self, dir: i32, radius: usize) -> HexCoord { - let s = Self::DIRECTIONS[(dir % 6) as usize] * radius as i32; - return Self::from_hex(self.hex.xy() + s.xy()); - } - - pub fn get_neighbor(&self, dir: usize) -> HexCoord { - let d = Self::DIRECTIONS[dir % 6]; - return Self::from_hex(self.hex.xy() + d.xy()); - } - - pub fn get_neighbors(&self) -> [HexCoord; 6] { - return [ - self.get_neighbor(0), - self.get_neighbor(1), - self.get_neighbor(2), - self.get_neighbor(3), - self.get_neighbor(4), - self.get_neighbor(5), - ]; - } - - pub fn hex_select(&self, radius: usize, include_center: bool) -> Vec { - assert!(radius != 0, "Radius cannot be zero"); - let mut result = Vec::with_capacity(get_tile_count_in_range(radius)); - - if include_center { - result.push(*self); - } - - for k in 0..(radius + 1) { - let mut p = self.scale(4, k); - for i in 0..6 { - for _j in 0..k { - p = p.get_neighbor(i); - result.push(p); - } - } - } - - return result; - } - - pub fn hex_select_bounded( - &self, - radius: usize, - include_center: bool, - height: usize, - width: usize, - ) -> Vec { - assert!(radius != 0, "Radius cannot be zero"); - let mut result = Vec::with_capacity(get_tile_count_in_range(radius)); - - if include_center { - if self.is_in_bounds(height, width) { - result.push(*self); - } - } - - for k in 0..(radius + 1) { - let mut p = self.scale(4, k); - for i in 0..6 { - for _j in 0..k { - p = p.get_neighbor(i); - if p.is_in_bounds(height, width) { - result.push(p); - } - } - } - } - - return result; - } - - pub fn select_ring(&self, radius: usize) -> Vec { - assert!(radius != 0, "Radius cannot be zero"); - let mut result = Vec::with_capacity(radius * 6); - - let mut p = self.scale(4, radius); - - // if radius == 1 { - // result.push(*self); - // return result; - // } - - for i in 0..6 { - for _j in 0..radius { - result.push(p); - p = p.get_neighbor(i); - } - } - - return result; - } -} diff --git a/engine/world_generation/src/lib.rs b/engine/world_generation/src/lib.rs index 3326bb4..92f287c 100644 --- a/engine/world_generation/src/lib.rs +++ b/engine/world_generation/src/lib.rs @@ -1,11 +1,10 @@ +pub mod biome_asset; pub mod biome_painter; pub mod consts; pub mod generators; pub mod heightmap; -pub mod hex_utils; pub mod map; pub mod prelude; pub mod states; pub mod tile_manager; pub mod tile_mapper; -pub mod biome_asset; diff --git a/engine/world_generation/src/map/biome_map.rs b/engine/world_generation/src/map/biome_map.rs index 000a8f7..023b67e 100644 --- a/engine/world_generation/src/map/biome_map.rs +++ b/engine/world_generation/src/map/biome_map.rs @@ -5,10 +5,11 @@ use bevy::{ use noise::NoiseFn; use rayon::iter::{IntoParallelIterator, ParallelIterator}; -use super::chunk::Chunk; +use hex::prelude::*; #[derive(Clone, Resource)] -pub struct BiomeMap { +pub struct BiomeMap +{ pub height: usize, pub width: usize, pub size: UVec2, @@ -17,26 +18,33 @@ pub struct BiomeMap { } #[derive(Default, Clone, Copy)] -pub struct BiomeData { +pub struct BiomeData +{ pub moisture: f32, pub temperature: f32, pub continentality: f32, } -impl Into for &BiomeData { - fn into(self) -> Vec3 { +impl Into for &BiomeData +{ + fn into(self) -> Vec3 + { return Vec3::new(self.moisture, self.temperature, self.continentality); } } -impl Into for BiomeData { - fn into(self) -> Vec3 { +impl Into for BiomeData +{ + fn into(self) -> Vec3 + { return Vec3::new(self.moisture, self.temperature, self.continentality); } } -impl BiomeMap { - pub fn new(size: UVec2, biome_count: usize) -> Self { +impl BiomeMap +{ + pub fn new(size: UVec2, biome_count: usize) -> Self + { let len = size.x as usize * size.y as usize * Chunk::AREA; return BiomeMap { size, @@ -47,14 +55,17 @@ impl BiomeMap { }; } - pub fn blend(&mut self, count: usize) { + pub fn blend(&mut self, count: usize) + { assert!(count != 0, "Count cannot be 0"); - for _ in 0..count { + for _ in 0..count + { self.blend_once(); } } - fn blend_once(&mut self) { + fn blend_once(&mut self) + { let c: Vec = (0..self.chunks.len()) .into_par_iter() .map(|i| &self.chunks[i]) @@ -63,7 +74,8 @@ impl BiomeMap { .into_par_iter() .map(|y| { let mut new_tiles = Vec::with_capacity(self.width); - for x in 0..Chunk::SIZE { + for x in 0..Chunk::SIZE + { let tx = x as u32 + chunk.offset.x * Chunk::SIZE as u32; let ty = y as u32 + chunk.offset.y * Chunk::SIZE as u32; let kernel = self.get_kernel(tx as i32, ty as i32); @@ -76,7 +88,8 @@ impl BiomeMap { }); let sum: f32 = r.iter().sum(); - if sum == 0. { + if sum == 0. + { new_tiles.push(vec![0.; self.biome_count]); continue; } @@ -96,7 +109,8 @@ impl BiomeMap { self.chunks = c; } - fn get_kernel(&self, x: i32, y: i32) -> [Option<&Vec>; 9] { + fn get_kernel(&self, x: i32, y: i32) -> [Option<&Vec>; 9] + { return [ self.get_biome(x - 1, y - 1), self.get_biome(x, y - 1), @@ -110,11 +124,14 @@ impl BiomeMap { ]; } - pub fn get_biome(&self, x: i32, y: i32) -> Option<&Vec> { - if x < 0 || y < 0 { + pub fn get_biome(&self, x: i32, y: i32) -> Option<&Vec> + { + if x < 0 || y < 0 + { return None; } - if x >= self.width as i32 || y >= self.height as i32 { + if x >= self.width as i32 || y >= self.height as i32 + { return None; } @@ -125,7 +142,8 @@ impl BiomeMap { return Some(chunk.get_biome(x as usize - cx * Chunk::SIZE, y as usize - cy * Chunk::SIZE)); } - pub fn get_biome_id(&self, x: usize, y: usize) -> usize { + pub fn get_biome_id(&self, x: usize, y: usize) -> usize + { let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize; let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize; @@ -134,7 +152,8 @@ impl BiomeMap { return chunk.get_biome_id(x - (cx * Chunk::SIZE), y - (cy * Chunk::SIZE)); } - pub fn get_biome_id_dithered(&self, x: usize, y: usize, noise: &impl NoiseFn, scale: f64) -> usize { + pub fn get_biome_id_dithered(&self, x: usize, y: usize, noise: &impl NoiseFn, scale: f64) -> usize + { let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize; let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize; @@ -143,7 +162,8 @@ impl BiomeMap { return chunk.get_biome_id_dithered(x - (cx * Chunk::SIZE), y - (cy * Chunk::SIZE), noise, scale); } - pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData { + pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData + { let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize; let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize; @@ -154,28 +174,35 @@ impl BiomeMap { } #[derive(Clone)] -pub struct BiomeChunk { +pub struct BiomeChunk +{ pub tiles: Vec>, pub offset: UVec2, pub data: [BiomeData; Chunk::AREA], } -impl BiomeChunk { - pub fn get_biome(&self, x: usize, y: usize) -> &Vec { +impl BiomeChunk +{ + pub fn get_biome(&self, x: usize, y: usize) -> &Vec + { return &self.tiles[x + y * Chunk::SIZE]; } - pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData { + pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData + { return &self.data[x + y * Chunk::SIZE]; } - pub fn get_biome_id(&self, x: usize, y: usize) -> usize { + pub fn get_biome_id(&self, x: usize, y: usize) -> usize + { let b = self.get_biome(x, y); let mut max = 0.; let mut idx = 0; - for i in 0..b.len() { + for i in 0..b.len() + { let blend = b[i]; - if blend > max { + if blend > max + { max = blend; idx = i; } @@ -183,17 +210,21 @@ impl BiomeChunk { return idx; } - pub fn get_biome_id_dithered(&self, x: usize, y: usize, noise: &impl NoiseFn, scale: f64) -> usize { + pub fn get_biome_id_dithered(&self, x: usize, y: usize, noise: &impl NoiseFn, scale: f64) -> usize + { let mut cur_id = self.get_biome_id(x, y); let b = self.get_biome(x, y); - let n = (noise.get([x as f64 / scale, y as f64 / scale]) as f32 - 0.5)/ 2.0; + let n = (noise.get([x as f64 / scale, y as f64 / scale]) as f32 - 0.5) / 2.0; let mut max = b[cur_id] + n; - for i in 0..b.len() { + for i in 0..b.len() + { let blend = b[i]; - if blend == 0. { + if blend == 0. + { continue; } - if blend > max { + if blend > max + { max = blend + n; cur_id = i; } @@ -204,18 +235,22 @@ impl BiomeChunk { } #[cfg(test)] -mod tests { +mod tests +{ use super::*; #[test] - fn biome_blend() { + fn biome_blend() + { let mut biome = BiomeMap::new(UVec2::splat(4), 8); let w = biome.size.x as usize; let h = biome.size.y as usize; - for y in 0..h { - for x in 0..w { + for y in 0..h + { + for x in 0..w + { let mut b = vec![0.; biome.biome_count]; let idx = (x + y) % biome.biome_count; b[idx] = 1.; @@ -227,7 +262,8 @@ mod tests { assert!(biome.chunks.iter().all(|f| f.tiles.len() == Chunk::AREA), "Data Lost"); } - fn generate_chunk(x: usize, y: usize, biome: Vec) -> BiomeChunk { + fn generate_chunk(x: usize, y: usize, biome: Vec) -> BiomeChunk + { let chunk = BiomeChunk { offset: UVec2::new(x as u32, y as u32), data: [BiomeData::default(); Chunk::AREA], diff --git a/engine/world_generation/src/map/chunk.rs b/engine/world_generation/src/map/chunk.rs deleted file mode 100644 index 893a4fb..0000000 --- a/engine/world_generation/src/map/chunk.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::hex_utils::SHORT_DIAGONAL; -use bevy::prelude::*; - - -#[derive(Clone)] -pub struct Chunk { - pub heights: [f32; Chunk::AREA], - pub textures: [[u32; 2]; Chunk::AREA], - // pub biome_data: [BiomeData; Chunk::AREA], - pub biome_id: [usize; Chunk::AREA], - pub chunk_offset: IVec2, - pub min_level: f32, - pub max_level: f32, -} - -impl Default for Chunk { - fn default() -> Self { - Self { - heights: [0.; Chunk::AREA], - textures: [[0; 2]; Chunk::AREA], - // biome_data: [BiomeData::default(); Chunk::AREA], - biome_id: [0; Chunk::AREA], - chunk_offset: Default::default(), - min_level: 0.0, - max_level: 0.0, - } - } -} - -impl Chunk { - pub const SIZE: usize = 64; - pub const AREA: usize = Chunk::SIZE * Chunk::SIZE; - pub const WORLD_WIDTH: f32 = Chunk::SIZE as f32 * SHORT_DIAGONAL; - pub const WORLD_HEIGHT: f32 = Chunk::SIZE as f32 * 1.5; - pub const WORLD_SIZE: Vec2 = Vec2::new(Chunk::WORLD_WIDTH, Chunk::WORLD_HEIGHT); - - pub fn get_pos_z_edge(&self) -> [f32; Chunk::SIZE] { - let mut data = [0.; Chunk::SIZE]; - - for x in 0..Chunk::SIZE { - let idx = x + (Chunk::SIZE - 1) * Chunk::SIZE; - data[x] = self.heights[idx]; - } - - return data; - } - - pub fn get_neg_z_edge(&self) -> [f32; Chunk::SIZE] { - let mut data = [0.; Chunk::SIZE]; - - for x in 0..Chunk::SIZE { - data[x] = self.heights[x]; - } - - return data; - } - - pub fn get_pos_x_edge(&self) -> [f32; Chunk::SIZE] { - let mut data = [0.; Chunk::SIZE]; - - for z in 0..Chunk::SIZE { - let idx = (Chunk::SIZE - 1) + z * Chunk::SIZE; - data[z] = self.heights[idx]; - } - - return data; - } - - pub fn get_neg_x_edge(&self) -> [f32; Chunk::SIZE] { - let mut data = [0.; Chunk::SIZE]; - - for z in 0..Chunk::SIZE { - let idx = z * Chunk::SIZE; - data[z] = self.heights[idx]; - } - - return data; - } -} diff --git a/engine/world_generation/src/map/config.rs b/engine/world_generation/src/map/config.rs index 766c8e9..1b10685 100644 --- a/engine/world_generation/src/map/config.rs +++ b/engine/world_generation/src/map/config.rs @@ -2,11 +2,12 @@ use bevy::prelude::*; use bevy_inspector_egui::InspectorOptions; use serde::{Deserialize, Serialize}; -use super::chunk::Chunk; +use hex::prelude::*; #[derive(Resource, Reflect, Default, Clone)] #[reflect(Resource)] -pub struct GenerationConfig { +pub struct GenerationConfig +{ pub sea_level: f64, pub border_size: f32, pub biome_blend: usize, @@ -17,23 +18,28 @@ pub struct GenerationConfig { pub size: UVec2, } -impl GenerationConfig { - pub fn get_total_width(&self) -> usize { +impl GenerationConfig +{ + pub fn get_total_width(&self) -> usize + { return self.size.x as usize * Chunk::SIZE; } - pub fn get_total_height(&self) -> usize { + pub fn get_total_height(&self) -> usize + { return self.size.y as usize * Chunk::SIZE; } } #[derive(Serialize, Deserialize, Default, Reflect, Clone, Debug)] -pub struct NoiseConfig { +pub struct NoiseConfig +{ pub scale: f64, pub layers: Vec, } #[derive(Reflect, InspectorOptions, Serialize, Deserialize, Debug, Clone, Default)] -pub struct GeneratorLayer { +pub struct GeneratorLayer +{ pub strength: f64, pub min_value: f64, pub base_roughness: f64, diff --git a/engine/world_generation/src/map/map.rs b/engine/world_generation/src/map/map.rs index 04c7844..bf31138 100644 --- a/engine/world_generation/src/map/map.rs +++ b/engine/world_generation/src/map/map.rs @@ -1,14 +1,11 @@ use bevy::prelude::*; +use hex::prelude::*; -use crate::hex_utils::*; - -use super::{ - chunk::Chunk, - mesh_chunk::MeshChunkData, -}; +use super::mesh_chunk::MeshChunkData; #[derive(Resource, Clone)] -pub struct Map { +pub struct Map +{ pub chunks: Vec, pub height: usize, pub width: usize, @@ -18,20 +15,25 @@ pub struct Map { pub biome_count: usize, } -impl Map { - pub fn get_tile_count(&self) -> usize { +impl Map +{ + pub fn get_tile_count(&self) -> usize + { return self.get_tile_width() * self.get_tile_height(); } - pub fn get_tile_width(&self) -> usize { + pub fn get_tile_width(&self) -> usize + { return self.width * Chunk::SIZE; } - pub fn get_tile_height(&self) -> usize { + pub fn get_tile_height(&self) -> usize + { return self.height * Chunk::SIZE; } - pub fn get_chunk_mesh_data(&self, chunk_index: usize) -> MeshChunkData { + pub fn get_chunk_mesh_data(&self, chunk_index: usize) -> MeshChunkData + { #[cfg(feature = "tracing")] let _spawn_span = info_span!("Chunk Mesh Data").entered(); let chunk = &self.chunks[chunk_index]; @@ -45,36 +47,45 @@ impl Map { }; } - fn get_distance_from_land(&self, chunk_offset: IVec2, range: usize) -> [f32; Chunk::AREA] { + fn get_distance_from_land(&self, chunk_offset: IVec2, range: usize) -> [f32; Chunk::AREA] + { #[cfg(feature = "tracing")] let _spawn_span = info_span!("Chunk Land Dist Data").entered(); let mut dists = [0.0; Chunk::AREA]; let cx = chunk_offset.x as usize * Chunk::SIZE; let cz = chunk_offset.y as usize * Chunk::SIZE; - for z in 0..Chunk::SIZE { - for x in 0..Chunk::SIZE { + for z in 0..Chunk::SIZE + { + for x in 0..Chunk::SIZE + { let coord = HexCoord::from_grid_pos(x + cx, z + cz); let index = coord.to_chunk_local_index(); - if !self.is_in_bounds(&coord) { + if !self.is_in_bounds(&coord) + { warn!("Coord is not in bounds!?"); } //Current tile is land tile - if self.sample_height(&coord) > self.sealevel { + if self.sample_height(&coord) > self.sealevel + { dists[index] = 0.0; continue; } //Find closest land tile if let Some(d) = self.hex_select_first(&coord, range, false, |_t, h, r| { - if h > self.sealevel { + if h > self.sealevel + { return Some(r as f32); } return None; - }) { + }) + { dists[index] = d; - } else { + } + else + { dists[index] = range as f32; } } @@ -82,14 +93,17 @@ impl Map { return dists; } - pub fn get_neighbors(&self, pos: &HexCoord) -> [Option; 6] { + pub fn get_neighbors(&self, pos: &HexCoord) -> [Option; 6] + { let mut results: [Option; 6] = [None; 6]; let w = self.width * Chunk::SIZE; let h = self.height * Chunk::SIZE; let n_tiles = pos.get_neighbors(); - for i in 0..6 { + for i in 0..6 + { let n_tile = n_tiles[i]; - if !n_tile.is_in_bounds(h, w) { + if !n_tile.is_in_bounds(h, w) + { continue; } let c_idx = n_tile.to_chunk_index(self.width); @@ -100,7 +114,8 @@ impl Map { return results; } - pub fn sample_height(&self, pos: &HexCoord) -> f32 { + pub fn sample_height(&self, pos: &HexCoord) -> f32 + { assert!( self.is_in_bounds(pos), "The provided coordinate is not within the map bounds" @@ -110,7 +125,8 @@ impl Map { return chunk.heights[pos.to_chunk_local_index()]; } - pub fn sample_height_mut(&mut self, pos: &HexCoord) -> &mut f32 { + pub fn sample_height_mut(&mut self, pos: &HexCoord) -> &mut f32 + { assert!( self.is_in_bounds(pos), "The provided coordinate is not within the map bounds" @@ -120,11 +136,13 @@ impl Map { return &mut chunk.heights[pos.to_chunk_local_index()]; } - pub fn is_in_bounds(&self, pos: &HexCoord) -> bool { + pub fn is_in_bounds(&self, pos: &HexCoord) -> bool + { return pos.is_in_bounds(self.height * Chunk::SIZE, self.width * Chunk::SIZE); } - pub fn get_biome_id(&self, pos: &HexCoord) -> usize { + pub fn get_biome_id(&self, pos: &HexCoord) -> usize + { assert!( self.is_in_bounds(pos), "The provided coordinate is not within the map bounds" @@ -134,13 +152,15 @@ impl Map { return chunk.biome_id[pos.to_chunk_local_index()]; } - pub fn get_center(&self) -> Vec3 { + pub fn get_center(&self) -> Vec3 + { let w = self.get_world_width(); let h = self.get_world_height(); return Vec3::new(w / 2., self.sealevel, h / 2.); } - pub fn get_center_with_height(&self) -> Vec3 { + pub fn get_center_with_height(&self) -> Vec3 + { let w = self.get_world_width(); let h = self.get_world_height(); let mut pos = Vec3::new(w / 2., self.sealevel, h / 2.); @@ -148,22 +168,27 @@ impl Map { return pos; } - pub fn get_world_width(&self) -> f32 { + pub fn get_world_width(&self) -> f32 + { return (self.width * Chunk::SIZE) as f32 * SHORT_DIAGONAL; } - pub fn get_world_height(&self) -> f32 { + pub fn get_world_height(&self) -> f32 + { return (self.height * Chunk::SIZE) as f32 * 1.5; } - pub fn get_world_size(&self) -> Vec2 { + pub fn get_world_size(&self) -> Vec2 + { return Vec2::new(self.get_world_width(), self.get_world_height()); } - pub fn set_height(&mut self, pos: &HexCoord, height: f32) { + pub fn set_height(&mut self, pos: &HexCoord, height: f32) + { self.chunks[pos.to_chunk_index(self.width)].heights[pos.to_chunk_local_index()] = height; } - pub fn create_crater(&mut self, pos: &HexCoord, radius: usize, depth: f32) -> Vec<(HexCoord, f32)> { + pub fn create_crater(&mut self, pos: &HexCoord, radius: usize, depth: f32) -> Vec<(HexCoord, f32)> + { assert!(radius != 0, "Radius cannot be zero"); let tiles = self.hex_select_mut(pos, radius, true, |p, h, r| { @@ -184,22 +209,30 @@ impl Map { { assert!(radius != 0, "Radius cannot be zero"); - let mut result = if include_center { + let mut result = if include_center + { Vec::with_capacity(get_tile_count_in_range(radius) + 1) - } else { + } + else + { Vec::with_capacity(get_tile_count_in_range(radius)) }; - if include_center { + if include_center + { let h = self.sample_height(¢er); result.push((op)(center, h, 0)); } - for k in 0..(radius + 1) { + for k in 0..(radius + 1) + { let mut p = center.scale(4, k); - for i in 0..6 { - for _j in 0..k { + for i in 0..6 + { + for _j in 0..k + { p = p.get_neighbor(i); - if self.is_in_bounds(&p) { + if self.is_in_bounds(&p) + { let h = self.sample_height(&p); result.push((op)(&p, h, k)); } @@ -222,23 +255,30 @@ impl Map { { assert!(radius != 0, "Radius cannot be zero"); - if include_center { + if include_center + { let h = self.sample_height(¢er); let r = (op)(center, h, 0); - if r.is_some() { + if r.is_some() + { return r; } } - for k in 0..(radius + 1) { + for k in 0..(radius + 1) + { let mut p = center.scale(4, k); - for i in 0..6 { - for _j in 0..k { + for i in 0..6 + { + for _j in 0..k + { p = p.get_neighbor(i); - if self.is_in_bounds(&p) { + if self.is_in_bounds(&p) + { let h = self.sample_height(&p); let r = (op)(&p, h, k); - if r.is_some() { + if r.is_some() + { return r; } } @@ -265,15 +305,20 @@ impl Map { "Start radius cannot be lower than end radius" ); - for k in start_radius..(end_radius + 1) { + for k in start_radius..(end_radius + 1) + { let mut p = center.scale(4, k); - for i in 0..6 { - for _j in 0..k { + for i in 0..6 + { + for _j in 0..k + { p = p.get_neighbor(i); - if self.is_in_bounds(&p) { + if self.is_in_bounds(&p) + { let h = self.sample_height(&p); let r = (op)(&p, h, k); - if r.is_some() { + if r.is_some() + { return r; } } @@ -296,22 +341,30 @@ impl Map { { assert!(radius != 0, "Radius cannot be zero"); - let mut result = if include_center { + let mut result = if include_center + { Vec::with_capacity(get_tile_count_in_range(radius) + 1) - } else { + } + else + { Vec::with_capacity(get_tile_count_in_range(radius)) }; - if include_center { + if include_center + { let h = self.sample_height_mut(¢er); result.push((op)(center, h, 0)); } - for k in 0..(radius + 1) { + for k in 0..(radius + 1) + { let mut p = center.scale(4, k); - for i in 0..6 { - for _j in 0..k { + for i in 0..6 + { + for _j in 0..k + { p = p.get_neighbor(i); - if self.is_in_bounds(&p) { + if self.is_in_bounds(&p) + { let h = self.sample_height_mut(&p); result.push((op)(&p, h, k)); } diff --git a/engine/world_generation/src/map/map_utils.rs b/engine/world_generation/src/map/map_utils.rs index 21c9a08..a9808b2 100644 --- a/engine/world_generation/src/map/map_utils.rs +++ b/engine/world_generation/src/map/map_utils.rs @@ -4,9 +4,9 @@ use bevy::{math::VectorSpace, prelude::*}; use image::ImageBuffer; use rayon::prelude::*; -use crate::hex_utils::HexCoord; +use hex::prelude::*; -use super::{biome_map::BiomeMap, chunk::Chunk, map::Map}; +use super::{biome_map::BiomeMap, map::Map}; pub fn render_image( size: UVec2, diff --git a/engine/world_generation/src/map/mesh_chunk.rs b/engine/world_generation/src/map/mesh_chunk.rs index 290f211..a5df6af 100644 --- a/engine/world_generation/src/map/mesh_chunk.rs +++ b/engine/world_generation/src/map/mesh_chunk.rs @@ -2,9 +2,7 @@ use std::collections::VecDeque; use bevy::math::IVec2; -use crate::hex_utils::HexCoord; - -use super::chunk::Chunk; +use hex::prelude::*; pub struct MeshChunkData { diff --git a/engine/world_generation/src/map/mod.rs b/engine/world_generation/src/map/mod.rs index fad9755..2083c67 100644 --- a/engine/world_generation/src/map/mod.rs +++ b/engine/world_generation/src/map/mod.rs @@ -1,6 +1,5 @@ -pub mod chunk; -pub mod mesh_chunk; +pub mod biome_map; pub mod config; pub mod map; -pub mod biome_map; -pub mod map_utils; \ No newline at end of file +pub mod map_utils; +pub mod mesh_chunk; diff --git a/engine/world_generation/src/prelude.rs b/engine/world_generation/src/prelude.rs index 3dbc12b..96d9f04 100644 --- a/engine/world_generation/src/prelude.rs +++ b/engine/world_generation/src/prelude.rs @@ -1,5 +1,4 @@ pub use crate::consts::*; -pub use crate::map::chunk::*; pub use crate::map::config::*; pub use crate::map::map::*; pub use crate::map::mesh_chunk::*; diff --git a/game/buildings/Cargo.toml b/game/buildings/Cargo.toml index 2fc4f53..5459f99 100644 --- a/game/buildings/Cargo.toml +++ b/game/buildings/Cargo.toml @@ -18,6 +18,7 @@ bevy_asset_loader = { version = "0.25.0", features = [ "standard_dynamic_assets", "3d", ] } +hex = { path = "../../engine/hex" } [features] tracing = [] diff --git a/game/buildings/src/build_queue.rs b/game/buildings/src/build_queue.rs index 6e69514..4b64a3e 100644 --- a/game/buildings/src/build_queue.rs +++ b/game/buildings/src/build_queue.rs @@ -1,15 +1,17 @@ - use bevy::prelude::Resource; +use hex::prelude::*; use shared::building::BuildingIdentifier; -use world_generation::hex_utils::HexCoord; #[derive(Resource)] -pub struct BuildQueue { +pub struct BuildQueue +{ pub queue: Vec, } -impl Default for BuildQueue { - fn default() -> Self { +impl Default for BuildQueue +{ + fn default() -> Self + { Self { queue: Default::default(), } @@ -17,7 +19,8 @@ impl Default for BuildQueue { } #[derive(PartialEq, Eq)] -pub struct QueueEntry { +pub struct QueueEntry +{ pub building: BuildingIdentifier, pub pos: HexCoord, } diff --git a/game/buildings/src/buildings_map.rs b/game/buildings/src/buildings_map.rs index 620463b..2a08ba1 100644 --- a/game/buildings/src/buildings_map.rs +++ b/game/buildings/src/buildings_map.rs @@ -1,21 +1,26 @@ use bevy::prelude::*; -use world_generation::{hex_utils::HexCoord, prelude::Chunk}; +use hex::prelude::*; #[derive(Resource)] -pub struct BuildingMap { +pub struct BuildingMap +{ pub chunks: Vec, pub size: UVec2, } -impl BuildingMap { - pub fn new(size: UVec2) -> Self { +impl BuildingMap +{ + pub fn new(size: UVec2) -> Self + { let mut db = BuildingMap { size, chunks: Vec::with_capacity(size.length_squared() as usize), }; - for y in 0..size.y as i32 { - for x in 0..size.x as i32 { + for y in 0..size.y as i32 + { + for x in 0..size.x as i32 + { let offset = IVec2::new(x, y); let index = (x + y * size.x as i32) as usize; db.chunks.push(BuildingChunk::new(offset, index)); @@ -25,7 +30,8 @@ impl BuildingMap { return db; } - pub fn get_buildings_in_range(&self, coord: &HexCoord, radius: usize) -> Vec<&BuildingEntry> { + pub fn get_buildings_in_range(&self, coord: &HexCoord, radius: usize) -> Vec<&BuildingEntry> + { assert!(radius != 0, "Radius cannot be zero"); let w = self.size.x as usize * Chunk::SIZE; @@ -34,10 +40,13 @@ impl BuildingMap { return self.get_buildings_in_coords(coords); } - pub fn get_buildings_in_coords(&self, coords: Vec) -> Vec<&BuildingEntry> { + pub fn get_buildings_in_coords(&self, coords: Vec) -> Vec<&BuildingEntry> + { let mut result = Vec::new(); - for coord in &coords { - if let Some(buidling) = self.get_building(coord) { + for coord in &coords + { + if let Some(buidling) = self.get_building(coord) + { result.push(buidling); } } @@ -45,25 +54,30 @@ impl BuildingMap { return result; } - pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> { + pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> + { let chunk = &self.chunks[coord.to_chunk_index(self.size.x as usize)]; return chunk.get_building(coord); } - pub fn add_building(&mut self, entry: BuildingEntry) { + pub fn add_building(&mut self, entry: BuildingEntry) + { let chunk = &mut self.chunks[entry.coord.to_chunk_index(self.size.x as usize)]; chunk.add_building(entry); } } -pub struct BuildingChunk { +pub struct BuildingChunk +{ pub entries: Vec, pub index: usize, pub offset: IVec2, } -impl BuildingChunk { - pub fn new(offset: IVec2, index: usize) -> Self { +impl BuildingChunk +{ + pub fn new(offset: IVec2, index: usize) -> Self + { return BuildingChunk { entries: Vec::new(), index, @@ -71,16 +85,19 @@ impl BuildingChunk { }; } - pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> { + pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> + { return self.entries.iter().find(|b| &b.coord == coord); } - pub fn add_building(&mut self, entry: BuildingEntry) { + pub fn add_building(&mut self, entry: BuildingEntry) + { self.entries.push(entry); } } -pub struct BuildingEntry { +pub struct BuildingEntry +{ pub coord: HexCoord, pub entity: Entity, pub is_main: bool, @@ -89,8 +106,10 @@ pub struct BuildingEntry { pub child_entities: Option>, } -impl BuildingEntry { - pub fn new(coord: HexCoord, entity: Entity) -> Self { +impl BuildingEntry +{ + pub fn new(coord: HexCoord, entity: Entity) -> Self + { return BuildingEntry { coord, entity, @@ -101,7 +120,8 @@ impl BuildingEntry { }; } - pub fn new_with_children(coord: HexCoord, entity: Entity, children: Vec) -> BuildingEntry { + pub fn new_with_children(coord: HexCoord, entity: Entity, children: Vec) -> BuildingEntry + { return BuildingEntry { coord, entity, @@ -112,7 +132,8 @@ impl BuildingEntry { }; } - pub fn new_with_parent(coord: HexCoord, entity: Entity, main: Entity) -> BuildingEntry { + pub fn new_with_parent(coord: HexCoord, entity: Entity, main: Entity) -> BuildingEntry + { return BuildingEntry { coord, entity, diff --git a/game/buildings/src/footprint.rs b/game/buildings/src/footprint.rs index 74238fc..a5e25d7 100644 --- a/game/buildings/src/footprint.rs +++ b/game/buildings/src/footprint.rs @@ -1,7 +1,7 @@ use bevy::math::{IVec2, Vec3Swizzles}; +use hex::prelude::*; use serde::{Deserialize, Serialize}; use shared::coords::CoordsCollection; -use world_generation::hex_utils::HexCoord; #[derive(Serialize, Deserialize, Debug)] pub struct BuildingFootprint @@ -21,7 +21,7 @@ impl BuildingFootprint let n_points: Vec = self .footprint .iter() - .flat_map(|p| HexCoord::from_hex(*p).get_neighbors()) + .flat_map(|p| HexCoord::from_axial(*p).get_neighbors()) .map(|c| c.hex.xy()) .filter(|p| !self.footprint.contains(p)) .collect(); diff --git a/game/main/Cargo.toml b/game/main/Cargo.toml index 7690180..3c62276 100644 --- a/game/main/Cargo.toml +++ b/game/main/Cargo.toml @@ -27,6 +27,8 @@ bevy_asset_loader = { version = "0.25.0", features = [ ] } ron = "0.12.0" image = "0.25.9" +hex = { path = "../../engine/hex" } + # bevy_lunex = "0.2.4" [features] diff --git a/game/main/src/camera_system/camera_plugin.rs b/game/main/src/camera_system/camera_plugin.rs index 424bcf8..ba190d3 100644 --- a/game/main/src/camera_system/camera_plugin.rs +++ b/game/main/src/camera_system/camera_plugin.rs @@ -3,9 +3,9 @@ use bevy::core_pipeline::prepass::DepthPrepass; use bevy::input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel}; use bevy::prelude::*; use bevy::window::{CursorGrabMode, CursorOptions, PrimaryWindow}; +use hex::prelude::*; use shared::sets::GameplaySet; use shared::tags::MainCamera; -use world_generation::hex_utils::HexCoord; use world_generation::prelude::Map; use world_generation::states::GeneratorState; diff --git a/game/main/src/camera_system/components.rs b/game/main/src/camera_system/components.rs index 56d2a6c..e007c4c 100644 --- a/game/main/src/camera_system/components.rs +++ b/game/main/src/camera_system/components.rs @@ -1,6 +1,6 @@ use bevy::prelude::*; +use hex::prelude::*; use rayon::str; -use world_generation::prelude::Chunk; #[derive(Component, Reflect)] #[reflect(Component)] diff --git a/game/main/src/map_rendering/map_init.rs b/game/main/src/map_rendering/map_init.rs index d7dbb3a..93d17ca 100644 --- a/game/main/src/map_rendering/map_init.rs +++ b/game/main/src/map_rendering/map_init.rs @@ -4,13 +4,14 @@ use bevy::{light::NotShadowCaster, pbr::ExtendedMaterial, prelude::*}; use bevy_asset_loader::prelude::*; use bevy_inspector_egui::quick::ResourceInspectorPlugin; +use hex::prelude::*; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use shared::states::{AssetLoadState, GameplayState, MenuState}; + use world_generation::{ biome_asset::{BiomeAsset, BiomeAssetPlugin}, biome_painter::*, heightmap::generate_heightmap, - hex_utils::{offset_to_index, SHORT_DIAGONAL}, map::biome_map::BiomeMap, prelude::*, tile_manager::*, diff --git a/game/main/src/utlis/chunk_utils.rs b/game/main/src/utlis/chunk_utils.rs index 12f5746..a78fe26 100644 --- a/game/main/src/utlis/chunk_utils.rs +++ b/game/main/src/utlis/chunk_utils.rs @@ -7,6 +7,7 @@ use bevy::{ mesh::Mesh, }; use bevy_rapier3d::geometry::{Collider, TriMeshFlags}; +use hex::prelude::*; use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator}; use world_generation::{ biome_painter::BiomePainter, @@ -14,8 +15,7 @@ use world_generation::{ chunk_colliders::generate_chunk_collider, mesh_generator::{generate_chunk_mesh, generate_chunk_water_mesh}, }, - hex_utils::offset_to_world, - prelude::{Chunk, Map, MeshChunkData}, + prelude::{Map, MeshChunkData}, tile_manager::TileAsset, tile_mapper::TileMapperAsset, }; diff --git a/game/main/src/utlis/tile_selection_plugin.rs b/game/main/src/utlis/tile_selection_plugin.rs index 41475ea..5725915 100644 --- a/game/main/src/utlis/tile_selection_plugin.rs +++ b/game/main/src/utlis/tile_selection_plugin.rs @@ -1,10 +1,12 @@ use bevy::{prelude::*, window::PrimaryWindow}; use bevy_rapier3d::{plugin::ReadRapierContext, prelude::QueryFilter}; +use hex::prelude::*; use shared::{ resources::{TileContact, TileUnderCursor}, tags::MainCamera, }; -use world_generation::{hex_utils::HexCoord, prelude::Map, states::GeneratorState}; +use world_generation::{prelude::Map, states::GeneratorState}; + pub struct TileSelectionPlugin; impl Plugin for TileSelectionPlugin diff --git a/game/shared/Cargo.toml b/game/shared/Cargo.toml index d1096a0..7a5a351 100644 --- a/game/shared/Cargo.toml +++ b/game/shared/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" bevy = "0.18.0" serde = { version = "1.0.228", features = ["derive"] } world_generation = { path = "../../engine/world_generation" } +hex = { path = "../../engine/hex" } [features] diff --git a/game/shared/src/coords.rs b/game/shared/src/coords.rs index 45c0987..b799fdf 100644 --- a/game/shared/src/coords.rs +++ b/game/shared/src/coords.rs @@ -1,5 +1,5 @@ use bevy::prelude::*; -use world_generation::hex_utils::HexCoord; +use hex::prelude::*; #[derive(Default, Debug, Reflect)] pub struct CoordsCollection @@ -51,11 +51,11 @@ impl CoordsCollection pub fn get_coords(&self) -> Vec { - let center = HexCoord::from_hex(self.origin); + let center = HexCoord::from_axial(self.origin); return self .points .iter() - .map(|p| HexCoord::from_hex(p + self.origin).rotate_around(¢er, self.rotation)) + .map(|p| HexCoord::from_axial(p + self.origin).rotate_around(¢er, self.rotation)) .collect(); } } diff --git a/game/shared/src/events.rs b/game/shared/src/events.rs index 6644244..9247629 100644 --- a/game/shared/src/events.rs +++ b/game/shared/src/events.rs @@ -1,13 +1,15 @@ use bevy::prelude::*; -use world_generation::hex_utils::*; +use hex::prelude::*; #[derive(Message)] -pub enum TileModifiedEvent { +pub enum TileModifiedEvent +{ HeightChanged(HexCoord, f32), TypeChanged(HexCoord, usize), } #[derive(Message)] -pub struct ChunkModifiedEvent { +pub struct ChunkModifiedEvent +{ pub index: usize, } diff --git a/game/shared/src/resources.rs b/game/shared/src/resources.rs index 7a53ef9..a5eabda 100644 --- a/game/shared/src/resources.rs +++ b/game/shared/src/resources.rs @@ -1,18 +1,21 @@ use bevy::prelude::*; -use world_generation::hex_utils::HexCoord; +use hex::prelude::*; #[derive(Resource, Default)] pub struct TileUnderCursor(pub Option); #[derive(Clone, Copy)] -pub struct TileContact { +pub struct TileContact +{ pub tile: HexCoord, pub point: Vec3, pub surface: Vec3, } -impl TileContact { - pub fn new(tile: HexCoord, contact: Vec3, surface: Vec3) -> Self { +impl TileContact +{ + pub fn new(tile: HexCoord, contact: Vec3, surface: Vec3) -> Self + { return Self { tile, point: contact, diff --git a/game/units/Cargo.toml b/game/units/Cargo.toml index bdb8078..d35e418 100644 --- a/game/units/Cargo.toml +++ b/game/units/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] bevy = "0.18.0" world_generation = { path = "../../engine/world_generation" } +hex = { path = "../../engine/hex" } shared = { path = "../shared" } bevy_rapier3d = "0.33.0" serde = { version = "1.0.228", features = ["derive"] } diff --git a/game/units/src/components.rs b/game/units/src/components.rs index 686abca..4737f18 100644 --- a/game/units/src/components.rs +++ b/game/units/src/components.rs @@ -1,6 +1,6 @@ use bevy::{ecs::world::CommandQueue, prelude::*, tasks::Task}; +use hex::prelude::*; use serde::{Deserialize, Serialize}; -use world_generation::hex_utils::HexCoord; #[derive(Component, Debug)] pub struct Unit; @@ -13,7 +13,8 @@ pub struct LandUnit; pub struct NavalUnit; #[derive(Serialize, Deserialize, Debug, Clone, Copy)] -pub enum UnitDomain { +pub enum UnitDomain +{ Land, Air, Naval, diff --git a/game/units/src/nav_data.rs b/game/units/src/nav_data.rs index 5b909d4..dbb2507 100644 --- a/game/units/src/nav_data.rs +++ b/game/units/src/nav_data.rs @@ -1,21 +1,27 @@ use bevy::prelude::*; +use hex::prelude::*; use ordered_float::OrderedFloat; -use world_generation::{hex_utils::HexCoord, prelude::Map}; +use world_generation::prelude::Map; #[derive(Clone, Resource)] -pub struct NavData { +pub struct NavData +{ pub tiles: Vec, pub map_height: usize, pub map_width: usize, } -impl NavData { - pub fn get_neighbors(&self, coord: &HexCoord) -> Vec<(HexCoord, OrderedFloat)> { +impl NavData +{ + pub fn get_neighbors(&self, coord: &HexCoord) -> Vec<(HexCoord, OrderedFloat)> + { let mut neighbors = Vec::with_capacity(6); let cur_height = self.get_height(coord); - for i in 0..6 { + for i in 0..6 + { let n = coord.get_neighbor(i); - if !self.is_in_bounds(&n) { + if !self.is_in_bounds(&n) + { continue; } let n_height = self.get_height(&n); @@ -23,26 +29,32 @@ impl NavData { } return neighbors; } - pub fn get(&self, coord: &HexCoord) -> &NavTile { + pub fn get(&self, coord: &HexCoord) -> &NavTile + { return &self.tiles[coord.to_index(self.map_width)]; } - pub fn get_height(&self, coord: &HexCoord) -> f32 { + pub fn get_height(&self, coord: &HexCoord) -> f32 + { return self.tiles[coord.to_index(self.map_width)].height; } - pub fn is_in_bounds(&self, pos: &HexCoord) -> bool { + pub fn is_in_bounds(&self, pos: &HexCoord) -> bool + { return pos.is_in_bounds(self.map_height, self.map_width); } - pub fn build(map: &Map) -> NavData { + pub fn build(map: &Map) -> NavData + { #[cfg(feature = "tracing")] let _path_span = info_span!("Build Nav Data").entered(); let mut tiles = Vec::with_capacity(map.get_tile_count()); let h = map.get_tile_height(); let w = map.get_tile_width(); - for y in 0..h { - for x in 0..w { + for y in 0..h + { + for x in 0..w + { let coord = HexCoord::from_grid_pos(x, y); let height = map.sample_height(&coord); let tile = NavTile { @@ -61,13 +73,16 @@ impl NavData { }; } - pub fn update(&mut self, map: &Map) { + pub fn update(&mut self, map: &Map) + { #[cfg(feature = "tracing")] let _path_span = info_span!("Update Nav Data").entered(); let h = map.get_tile_height(); let w = map.get_tile_width(); - for y in 0..h { - for x in 0..w { + for y in 0..h + { + for x in 0..w + { let coord = HexCoord::from_grid_pos(x, y); let height = map.sample_height(&coord); let tile = NavTile { @@ -79,7 +94,8 @@ impl NavData { } } } - pub fn update_tile(&mut self, coord: &HexCoord, height: f32, move_cost: f32) { + pub fn update_tile(&mut self, coord: &HexCoord, height: f32, move_cost: f32) + { let tile = &mut self.tiles[coord.to_index(self.map_width)]; tile.move_cost = move_cost; tile.height = height; @@ -87,14 +103,17 @@ impl NavData { } #[derive(Clone)] -pub struct NavTile { +pub struct NavTile +{ pub height: f32, pub move_cost: f32, pub coord: HexCoord, } -impl NavTile { - pub fn calculate_heuristic(&self, to: &HexCoord) -> OrderedFloat { +impl NavTile +{ + pub fn calculate_heuristic(&self, to: &HexCoord) -> OrderedFloat + { return (self.coord.distance(to) as f32).into(); } } diff --git a/game/units/src/units_plugin.rs b/game/units/src/units_plugin.rs index ad0b593..95143fa 100644 --- a/game/units/src/units_plugin.rs +++ b/game/units/src/units_plugin.rs @@ -5,9 +5,10 @@ use bevy::{ prelude::*, tasks::{futures, AsyncComputeTaskPool}, }; +use hex::prelude::*; use pathfinding::prelude::astar; use shared::{events::TileModifiedEvent, resources::TileUnderCursor, sets::GameplaySet}; -use world_generation::{hex_utils::HexCoord, prelude::Map, states::GeneratorState}; +use world_generation::{prelude::Map, states::GeneratorState}; #[cfg(debug_assertions)] use crate::units_debug_plugin::UnitsDebugPlugin; @@ -20,8 +21,10 @@ use crate::{ pub struct UnitsPlugin; -impl Plugin for UnitsPlugin { - fn build(&self, app: &mut App) { +impl Plugin for UnitsPlugin +{ + fn build(&self, app: &mut App) + { app.init_resource::(); app.add_plugins(UnitAssetPlugin); @@ -40,15 +43,20 @@ impl Plugin for UnitsPlugin { } } -fn build_navdata(mut commands: Commands, map: Res) { +fn build_navdata(mut commands: Commands, map: Res) +{ let nav_data = NavData::build(&map); commands.insert_resource(nav_data); } -fn update_navdata(mut tile_updates: MessageReader, mut nav_data: ResMut) { - for event in tile_updates.read() { - match event { - TileModifiedEvent::HeightChanged(coord, new_height) => { +fn update_navdata(mut tile_updates: MessageReader, mut nav_data: ResMut) +{ + for event in tile_updates.read() + { + match event + { + TileModifiedEvent::HeightChanged(coord, new_height) => + { nav_data.update_tile(coord, *new_height, 1.0); } _ => (), @@ -56,6 +64,7 @@ fn update_navdata(mut tile_updates: MessageReader, mut nav_da } } +#[allow(unused)] fn units_control(tile_under_cursor: Res) {} fn move_unit( @@ -63,22 +72,27 @@ fn move_unit( time: Res