diff --git a/engine/world_generation/src/biome_painter.rs b/engine/world_generation/src/biome_painter.rs index 15f9e4f..6b83bb1 100644 --- a/engine/world_generation/src/biome_painter.rs +++ b/engine/world_generation/src/biome_painter.rs @@ -64,6 +64,22 @@ impl BiomePainter { return biome; } + + pub fn sample_biome_index(&self, data: &BiomeData) -> usize { + assert!(self.biomes.length() != 0, "There are no biomes"); + let mut biome = 0; + let mut dist = f32::INFINITY; + + for i in 0..self.biomes.len() { + let d = self.biomes[i].distance(data.into()); + if d < dist { + biome = i; + dist = d; + } + } + + return biome; + } } create_asset_loader!( diff --git a/engine/world_generation/src/heightmap.rs b/engine/world_generation/src/heightmap.rs index c036a43..c924af8 100644 --- a/engine/world_generation/src/heightmap.rs +++ b/engine/world_generation/src/heightmap.rs @@ -1,4 +1,4 @@ -use bevy::math::IVec2; +use bevy::math::{IVec2, UVec2}; use bevy::prelude::{FloatExt, Vec2}; use bevy::utils::default; use bevy::utils::petgraph::data; @@ -10,7 +10,7 @@ use crate::map::biome_map::{self, BiomeChunk, BiomeData, BiomeMap}; use crate::prelude::*; pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> Map { - let biomes = &generate_biomes(cfg, seed); + let biomes = &generate_biomes(cfg, seed, painter); // let mut chunks: Vec = Vec::with_capacity(cfg.size.length_squared() as usize); let chunks = (0..cfg.size.y) .into_par_iter() @@ -29,13 +29,13 @@ pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePain }; } -pub fn generate_biomes(cfg: &GenerationConfig, seed: u32) -> BiomeMap { - let mut map = BiomeMap::new(cfg.size, 8); +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() .flat_map(|y| { (0..cfg.size.x).into_par_iter().map(move |x| { - return generate_biome_chunk(x as usize, y as usize, cfg, seed); + return generate_biome_chunk(x as usize, y as usize, cfg, seed, biome_painter); }) }) .collect(); @@ -43,8 +43,15 @@ pub fn generate_biomes(cfg: &GenerationConfig, seed: u32) -> BiomeMap { return map; } -pub fn generate_biome_chunk(chunk_x: usize, chunk_y: usize, cfg: &GenerationConfig, seed: u32) -> BiomeChunk { +pub fn generate_biome_chunk( + chunk_x: usize, + chunk_y: usize, + cfg: &GenerationConfig, + seed: u32, + biome_painter: &BiomePainter, +) -> BiomeChunk { let mut chunk = BiomeChunk { + offset: UVec2::new(chunk_x as u32, chunk_y as u32), data: [BiomeData::default(); Chunk::AREA], tiles: Vec::with_capacity(Chunk::AREA), }; @@ -78,11 +85,16 @@ pub fn generate_biome_chunk(chunk_x: usize, chunk_y: usize, cfg: &GenerationConf cfg.size.as_vec2(), cfg.border_size, ); - chunk.data[x + z * Chunk::SIZE] = BiomeData { - moisture, - temperature, - continentality, + let data = BiomeData { + moisture: moisture.clamp(0., 100.), + temperature: temperature.clamp(0., 100.), + continentality: continentality.clamp(0., 100.), }; + let mut b = vec![0.; biome_painter.biomes.len()]; + b[biome_painter.sample_biome_index(&data)] = 1.; + + chunk.data[x + z * Chunk::SIZE] = data; + chunk.tiles.push(b); } } @@ -103,15 +115,23 @@ pub fn generate_chunk( for z in 0..Chunk::SIZE { for x in 0..Chunk::SIZE { let biome_data = biome_chunk.get_biome_data(x, z); - let biome = biome_painter.sample_biome(biome_data); - let sample = sample_point( - x as f64 + chunk_x as f64 * Chunk::SIZE as f64, - z as f64 + chunk_z as f64 * Chunk::SIZE as f64, - &biome.noise, - &noise, - cfg.size.as_vec2(), - cfg.border_size, - ); + let biome_blend = biome_chunk.get_biome(x, z); + let mut sample = 0.; + for i in 0..biome_blend.len() { + let blend = biome_blend[i]; + if blend == 0. { + continue; + } + let biome = &biome_painter.biomes[i]; + sample += sample_point( + x as f64 + chunk_x as f64 * Chunk::SIZE as f64, + z as f64 + chunk_z as f64 * Chunk::SIZE as f64, + &biome.noise, + &noise, + cfg.size.as_vec2(), + cfg.border_size, + ) * blend; + } result[x + z * Chunk::SIZE] = sample; data[x + z * Chunk::SIZE] = biome_data.clone(); } diff --git a/engine/world_generation/src/map/biome_map.rs b/engine/world_generation/src/map/biome_map.rs index 3bfbf10..0b6fe41 100644 --- a/engine/world_generation/src/map/biome_map.rs +++ b/engine/world_generation/src/map/biome_map.rs @@ -6,6 +6,7 @@ use super::chunk::Chunk; pub struct BiomeMap { pub height: usize, pub width: usize, + pub size: UVec2, pub biome_count: usize, pub chunks: Vec, } @@ -33,6 +34,7 @@ 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: size, height: size.y as usize * Chunk::SIZE, width: size.x as usize * Chunk::SIZE, biome_count, @@ -57,7 +59,10 @@ impl BiomeMap { .map(|y| { let mut new_tiles = Vec::with_capacity(self.width); for x in 0..Chunk::SIZE { - let kernel = self.get_kernel(x as i32, y as i32); + 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); + let r = kernel .iter() .filter_map(|f| *f) @@ -77,6 +82,7 @@ impl BiomeMap { .flatten() .collect(); return BiomeChunk { + offset: chunk.offset, tiles, data: chunk.data, }; @@ -107,27 +113,27 @@ impl BiomeMap { return None; } - let cx = x as usize / Chunk::SIZE; - let cy = y as usize / Chunk::SIZE; - - let chunk = &self.chunks[cx + cy * Chunk::SIZE]; + let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize; + let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize; + let chunk = &self.chunks[cx + cy * self.size.x as usize]; return Some(chunk.get_biome(x as usize - cx * Chunk::SIZE, y as usize - cy * Chunk::SIZE)); } pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData { - let cx = x / Chunk::SIZE; - let cy = y / Chunk::SIZE; + let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize; + let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize; - let chunk = &self.chunks[cx + cy * Chunk::SIZE]; + let chunk = &self.chunks[cx + cy * self.size.x as usize]; - return chunk.get_biome_data(x - cx * Chunk::SIZE, y - cy * Chunk::SIZE); + return chunk.get_biome_data(x - (cx * Chunk::SIZE), y - (cy * Chunk::SIZE)); } } #[derive(Clone)] pub struct BiomeChunk { pub tiles: Vec>, + pub offset: UVec2, pub data: [BiomeData; Chunk::AREA], } @@ -148,9 +154,9 @@ mod tests { #[test] fn biome_blend() { - let mut biome = BiomeMap::new(UVec2::ONE * 16, 8); - let w = biome.width / Chunk::SIZE; - let h = biome.height / Chunk::SIZE; + 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 { @@ -162,10 +168,12 @@ mod tests { } biome.blend(8); + assert!(biome.chunks.iter().all(|f| f.tiles.len() == Chunk::AREA), "Data Lost"); } 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], tiles: (0..Chunk::AREA).into_iter().map(|_| biome.clone()).collect(), }; diff --git a/game/buildings/src/building_plugin.rs b/game/buildings/src/building_plugin.rs index ccccaa7..4188acb 100644 --- a/game/buildings/src/building_plugin.rs +++ b/game/buildings/src/building_plugin.rs @@ -16,7 +16,7 @@ impl Plugin for BuildingPugin { app.insert_resource(BuildQueue::default()); app.add_systems(Startup, init); - app.add_systems(Update, hq_placement.run_if(in_state(GameplayState::PlaceHQ))); + //app.add_systems(Update, hq_placement.run_if(in_state(GameplayState::PlaceHQ))); app.add_systems(PreUpdate, process_build_queue.run_if(in_state(GameplayState::Playing))); } diff --git a/game/main/assets b/game/main/assets index f809b72..2f1fb1b 160000 --- a/game/main/assets +++ b/game/main/assets @@ -1 +1 @@ -Subproject commit f809b7232a4395824d16c3ffef624f280987c66a +Subproject commit 2f1fb1ba3b08ea323d596f585952c8fd804f400f diff --git a/game/main/src/map_rendering/map_init.rs b/game/main/src/map_rendering/map_init.rs index 4ed9595..04ce150 100644 --- a/game/main/src/map_rendering/map_init.rs +++ b/game/main/src/map_rendering/map_init.rs @@ -206,19 +206,19 @@ fn create_heightmap( biome_painter: Res, ) { let config = GenerationConfig { - biome_blend: 3, + biome_blend: 16, continent_layer: NoiseConfig { scale: 450., layers: vec![GeneratorLayer { base_roughness: 2.14, roughness: 0.87, strength: 100., - min_value: -0.2, + min_value: 0., persistence: 0.77, is_rigid: false, weight: 0., weight_multi: 0., - layers: 4, + layers: 1, first_layer_mask: false, }], }, @@ -228,12 +228,12 @@ fn create_heightmap( base_roughness: 2.14, roughness: 0.87, strength: 100., - min_value: -0.2, + min_value: 0., persistence: 0.77, is_rigid: false, weight: 0., weight_multi: 0., - layers: 4, + layers: 1, first_layer_mask: false, }], }, @@ -243,18 +243,18 @@ fn create_heightmap( base_roughness: 2.14, roughness: 0.87, strength: 100., - min_value: -0.2, + min_value: 0., persistence: 0.77, is_rigid: false, weight: 0., weight_multi: 0., - layers: 4, + layers: 1, first_layer_mask: false, }], }, sea_level: 8.5, border_size: 64., - size: UVec2::splat(1024 / Chunk::SIZE as u32), + size: UVec2::splat(16), // size: UVec2::splat(1), }; let heightmap = generate_heightmap(&config, 42069, &biome_painter);