From 836be517a21e2a602129396afdf201cc2e9204bb Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Sun, 11 Dec 2022 22:25:09 +0100 Subject: [PATCH] WIP --- Cargo.lock | 26 ++++--- build_all.sh.ps1 | 16 ++--- planet/Cargo.toml | 3 + planet/src/human_group.rs | 14 +++- planet/src/saving/mod.rs | 2 +- planet/src/saving/terrain_cell.rs | 115 +++++++++++++++++++++++++++--- planet/src/saving/world.rs | 12 ++-- planet/src/terrain_cell.rs | 23 +++--- planet/src/world.rs | 106 ++++++++++++++++++++------- planet/src/world_manager.rs | 49 +++++++------ src/gui/windows/tile_info.rs | 3 + src/main.rs | 13 +++- src/planet_renderer.rs | 49 +++++-------- 13 files changed, 303 insertions(+), 128 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dbd5525..472856f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -804,6 +804,15 @@ dependencies = [ "winit", ] +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -871,9 +880,9 @@ checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "calloop" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bcf530afb40e45e14440701e5e996d7fd139e84a912a4d83a8d6a0fb3e58663" +checksum = "19457a0da465234abd76134a5c2a910c14bd3c5558463e4396ab9a37a328e465" dependencies = [ "log", "nix 0.25.1", @@ -2094,6 +2103,7 @@ name = "planet" version = "0.3.1" dependencies = [ "bevy", + "bincode", "crossbeam-channel", "rand", "serde", @@ -2305,18 +2315,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.148" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc" +checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.148" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c" +checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" dependencies = [ "proc-macro2", "quote", @@ -2596,9 +2606,9 @@ checksum = "375812fa44dab6df41c195cd2f7fecb488f6c09fbaafb62807488cefab642bff" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" diff --git a/build_all.sh.ps1 b/build_all.sh.ps1 index 3a7c7b8..e8dd506 100755 --- a/build_all.sh.ps1 +++ b/build_all.sh.ps1 @@ -1,18 +1,18 @@ #!/bin/env /bin/sh echo "Debug-build with features: minimal" -cargo build --no-default-features --features= && +cargo build -j 6 --no-default-features --features= && echo "Debug-build with features: logging" && -cargo build --no-default-features --features=logging && +cargo build -j 6 --no-default-features --features=logging && echo "Debug-build with features: render" && -cargo build --no-default-features --features=render && +cargo build -j 6 --no-default-features --features=render && echo "Debug-build with features: logging render" && -cargo build --no-default-features --features="logging,render" && +cargo build -j 6 --no-default-features --features="logging,render" && echo "Release-build with features: minimal" -cargo build --release --no-default-features --features= && +cargo build -j 6 --release --no-default-features --features= && echo "Release-build with features: logging" && -cargo build --release --no-default-features --features=logging && +cargo build -j 6 --release --no-default-features --features=logging && echo "Release-build with features: render" && -cargo build --release --no-default-features --features=render && +cargo build -j 6 --release --no-default-features --features=render && echo "Release-build with features: logging render" && -cargo build --release --no-default-features --features="logging,render" && +cargo build -j 6 --release --no-default-features --features="logging,render" && echo "Done!" \ No newline at end of file diff --git a/planet/Cargo.toml b/planet/Cargo.toml index 26f3223..77afcde 100644 --- a/planet/Cargo.toml +++ b/planet/Cargo.toml @@ -23,6 +23,9 @@ version = "1.0" default-features = false features = ["derive"] +[dependencies.bincode] +version = "1.3.3" + [dependencies.crossbeam-channel] version = "0.5.6" default-features = false diff --git a/planet/src/human_group.rs b/planet/src/human_group.rs index 2745b02..a6b7c4c 100644 --- a/planet/src/human_group.rs +++ b/planet/src/human_group.rs @@ -1,7 +1,17 @@ -use serde::{Deserialize, Serialize}; +use { + crate::World, + core::hash::Hash, + serde::{Deserialize, Serialize}, +}; -#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, Eq, PartialEq, Hash)] pub struct HumanGroup { pub id: u32, pub population: u32, } + +impl HumanGroup { + pub fn update(&self, _world: &World) { + // TODO: Anything + } +} diff --git a/planet/src/saving/mod.rs b/planet/src/saving/mod.rs index d93db9f..7558134 100644 --- a/planet/src/saving/mod.rs +++ b/planet/src/saving/mod.rs @@ -1,2 +1,2 @@ -// pub mod terrain_cell; +pub mod terrain_cell; pub mod world; diff --git a/planet/src/saving/terrain_cell.rs b/planet/src/saving/terrain_cell.rs index cdfc722..a52f04f 100644 --- a/planet/src/saving/terrain_cell.rs +++ b/planet/src/saving/terrain_cell.rs @@ -1,13 +1,15 @@ use { - crate::TerrainCell, - bevy::prelude::default, + crate::{HumanGroup, TerrainCell}, + bevy::prelude::{debug, default}, serde::{ de::{Error, MapAccess, SeqAccess, Visitor}, + ser::SerializeStruct, Deserialize, + Serialize, }, std::{ fmt::{self, Formatter}, - sync::Weak, + sync::Arc, }, }; @@ -24,6 +26,9 @@ impl<'de> Deserialize<'de> for TerrainCell { Temperature, LocalIteration, BiomePresences, + Height, + Width, + HumanGroups, } struct TerrainCellVisitor; @@ -39,25 +44,48 @@ impl<'de> Deserialize<'de> for TerrainCell { where V: SeqAccess<'de>, { + std::mem::transmute::(seq); + + let mut length = 0; let altitude = seq .next_element()? - .ok_or_else(|| Error::invalid_length(0, &self))?; + .ok_or_else(|| panic!("Invalid length {length}, expected 8"))?; + length += 1; let rainfall = seq .next_element()? - .ok_or_else(|| Error::invalid_length(1, &self))?; + .ok_or_else(|| panic!("Invalid length {length}, expected 8"))?; + length += 1; let temperature = seq .next_element()? - .ok_or_else(|| Error::invalid_length(2, &self))?; + .ok_or_else(|| panic!("Invalid length {length}, expected 8"))?; + length += 1; let local_iteration = seq .next_element()? - .ok_or_else(|| Error::invalid_length(3, &self))?; + .ok_or_else(|| panic!("Invalid length {length}, expected 8"))?; + length += 1; let biome_presences = seq .next_element()? - .ok_or_else(|| Error::invalid_length(4, &self))?; + .ok_or_else(|| panic!("Invalid length {length}, expected 8"))?; + length += 1; + + let height = seq + .next_element()? + .ok_or_else(|| panic!("Invalid length {length}, expected 8"))?; + length += 1; + + let width = seq + .next_element()? + .ok_or_else(|| panic!("Invalid length {length}, expected 8"))?; + length += 1; + + let human_groups = seq + .next_element::>()? + .ok_or_else(|| panic!("Invalid length {length}, expected 8"))?; + // length += 1; Ok(TerrainCell { altitude, @@ -67,6 +95,9 @@ impl<'de> Deserialize<'de> for TerrainCell { biome_presences, x: default(), y: default(), + human_groups: human_groups.iter().map(|group| Arc::new(*group)).collect(), + height, + width, }) } @@ -79,6 +110,9 @@ impl<'de> Deserialize<'de> for TerrainCell { let mut temperature = None; let mut local_iteration = None; let mut biome_presences = None; + let mut height = None; + let mut width = None; + let mut human_groups: Option> = None; while let Some(key) = map.next_key()? { match key { @@ -112,6 +146,24 @@ impl<'de> Deserialize<'de> for TerrainCell { } biome_presences = Some(map.next_value()?); }, + Field::Height => { + if height.is_some() { + return Err(Error::duplicate_field("height")); + } + height = Some(map.next_value()?); + }, + Field::Width => { + if width.is_some() { + return Err(Error::duplicate_field("width")); + } + width = Some(map.next_value()?); + }, + Field::HumanGroups => { + if human_groups.is_some() { + return Err(Error::duplicate_field("human_groups")); + } + human_groups = Some(map.next_value()?); + }, } } @@ -122,6 +174,10 @@ impl<'de> Deserialize<'de> for TerrainCell { local_iteration.ok_or_else(|| Error::missing_field("local_iteration"))?; let biome_presences = biome_presences.ok_or_else(|| Error::missing_field("biome_presences"))?; + let height = height.ok_or_else(|| Error::missing_field("height"))?; + let width = width.ok_or_else(|| Error::missing_field("width"))?; + let human_groups = + human_groups.ok_or_else(|| Error::missing_field("human_groups"))?; Ok(TerrainCell { altitude, @@ -131,6 +187,9 @@ impl<'de> Deserialize<'de> for TerrainCell { biome_presences, x: default(), y: default(), + human_groups: human_groups.iter().map(|group| Arc::new(*group)).collect(), + height, + width, }) } } @@ -146,3 +205,43 @@ impl<'de> Deserialize<'de> for TerrainCell { deserializer.deserialize_struct("TerrainCell", FIELDS, TerrainCellVisitor) } } + +impl Serialize for TerrainCell { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let TerrainCell { + altitude, + rainfall, + temperature, + x: _x, + y: _y, + local_iteration, + biome_presences, + human_groups, + height, + width, + } = self; + + let human_groups = &human_groups + .iter() + .map(|group_arc| **group_arc) + .collect::>(); + + let mut serialized_struct = serializer.serialize_struct(stringify!(TerrainCell), 10)?; + serialized_struct.serialize_field(stringify!(altitude), altitude)?; + serialized_struct.serialize_field(stringify!(rainfall), rainfall)?; + serialized_struct.serialize_field(stringify!(temperature), temperature)?; + // #[skip] + // serialized_struct.serialize_field(stringify!(x), x)?; + // #[skip] + // serialized_struct.serialize_field(stringify!(y), y)?; + serialized_struct.serialize_field(stringify!(local_iteration), local_iteration)?; + serialized_struct.serialize_field(stringify!(biome_presences), biome_presences)?; + serialized_struct.serialize_field(stringify!(human_groups), human_groups)?; + serialized_struct.serialize_field(stringify!(height), height)?; + serialized_struct.serialize_field(stringify!(width), width)?; + serialized_struct.end() + } +} diff --git a/planet/src/saving/world.rs b/planet/src/saving/world.rs index 799cb04..d4eac3f 100644 --- a/planet/src/saving/world.rs +++ b/planet/src/saving/world.rs @@ -1,6 +1,6 @@ use { crate::{TerrainCell, World}, - bevy::prelude::debug, + bevy::{prelude::debug, utils::default}, rand::{rngs::StdRng, SeedableRng}, serde::{ de::{Error, MapAccess, SeqAccess, Visitor}, @@ -137,6 +137,7 @@ impl<'de> Deserialize<'de> for World { rng: StdRng::seed_from_u64(seed as u64), iteration, + human_groups_to_update: default(), }; { let mut y = 0; @@ -219,10 +220,10 @@ impl<'de> Deserialize<'de> for World { let mut terrain: Vec> = terrain.ok_or_else(|| Error::missing_field("terrain"))?; - for x in 0..width as usize { - for y in 0..height as usize { - terrain[y][x].x = x; - terrain[y][x].y = y; + for x in 0..width as u32 { + for y in 0..height as u32 { + terrain[y as usize][x as usize].x = x; + terrain[y as usize][x as usize].y = y; } } @@ -279,6 +280,7 @@ impl<'de> Deserialize<'de> for World { rng: StdRng::seed_from_u64(seed as u64), iteration, + human_groups_to_update: default(), }; { let mut y = 0; diff --git a/planet/src/terrain_cell.rs b/planet/src/terrain_cell.rs index bb5ffee..5a633c4 100644 --- a/planet/src/terrain_cell.rs +++ b/planet/src/terrain_cell.rs @@ -1,22 +1,23 @@ use { crate::{perlin, BiomeType, HumanGroup, World}, - serde::{Deserialize, Serialize}, + std::sync::Arc, }; -#[derive(Debug, Clone, Default, Deserialize, Serialize)] +#[derive(Debug, Clone, Default)] pub struct TerrainCell { pub altitude: f32, pub rainfall: f32, pub temperature: f32, - #[serde(skip)] - pub x: usize, - #[serde(skip)] - pub y: usize, - pub local_iteration: usize, + pub x: u32, + pub y: u32, + pub local_iteration: u64, pub biome_presences: Vec<(BiomeType, f32)>, - pub human_groups: Vec, + pub human_groups: Vec>, + + pub height: f32, + pub width: f32, } impl TerrainCell { @@ -36,15 +37,15 @@ impl TerrainCell { self.get_next_local_random_int(world) as f32 / perlin::MAX_PERMUTATION_VALUE as f32 } - pub fn biome_presence(&self, biome: BiomeType) -> f32 { + pub fn biome_presence(&self, biome: BiomeType) -> Option { if let Some(presence) = self .biome_presences .iter() .find(|biome_presence| biome_presence.0 == biome) { - presence.1 + Some(presence.1) } else { - 0.0 + None } } } diff --git a/planet/src/world.rs b/planet/src/world.rs index 0a7759e..be18bcd 100644 --- a/planet/src/world.rs +++ b/planet/src/world.rs @@ -10,6 +10,7 @@ use { perlin, BiomeStats, BiomeType, + HumanGroup, TerrainCell, }, bevy::{ @@ -20,11 +21,12 @@ use { }, crossbeam_channel::Sender, rand::{rngs::StdRng, Rng, SeedableRng}, - serde::{Deserialize, Serialize}, + serde::Serialize, std::{ error::Error, f32::consts::{PI, TAU}, fmt::{Debug, Display}, + sync::{Arc, Weak}, }, }; @@ -91,6 +93,9 @@ pub struct World { #[serde(skip)] pub rng: StdRng, pub iteration: usize, + + #[serde(skip)] + pub human_groups_to_update: Vec>, } impl World { @@ -114,7 +119,7 @@ impl World { #[must_use] #[inline(always)] - pub fn cell_max_widht(&self) -> f32 { + pub fn cell_max_width(&self) -> f32 { self.width as f32 / World::CIRCUMFERENCE as f32 } @@ -134,25 +139,7 @@ impl World { min_temperature: World::MAX_TEMPERATURE, rng: StdRng::seed_from_u64(seed as u64), iteration: 0, - } - } - - pub fn async_new(width: u32, height: u32, seed: u32) -> World { - World { - width, - height, - seed, - terrain: vec![vec![default(); width.try_into().unwrap()]; height.try_into().unwrap()], - continent_offsets: [default(); World::NUM_CONTINENTS as usize], - continent_sizes: [default(); World::NUM_CONTINENTS as usize], - max_altitude: World::MIN_ALTITUDE, - min_altitude: World::MAX_ALTITUDE, - max_rainfall: World::MIN_RAINFALL, - min_rainfall: World::MAX_RAINFALL, - max_temperature: World::MIN_TEMPERATURE, - min_temperature: World::MAX_TEMPERATURE, - rng: StdRng::seed_from_u64(seed as u64), - iteration: 0, + human_groups_to_update: default(), } } @@ -176,6 +163,9 @@ impl World { send_progress(progress_sender, 0.0, "Generating biomes"); self.generate_biomes(progress_sender); + send_progress(progress_sender, 0.0, "Populating world"); + self.set_initial_human_groups(progress_sender); + Ok(()) } @@ -419,8 +409,10 @@ impl World { self.min_altitude = altitude; } - self.terrain[y][x].x = x; - self.terrain[y][x].y = y; + self.terrain[y][x].x = x as u32; + self.terrain[y][x].y = y as u32; + self.terrain[y][x].height = f32::sin(alpha) * self.cell_max_width(); + self.terrain[y][x].width = self.cell_max_width(); } } info!("Done generating altitude"); @@ -502,10 +494,10 @@ impl World { let latitude_modifier_2 = f32::cos(latitude_factor); let offset_cell_x_1 = - (width + x + f32::floor(latitude_modifier_2 * width as f32 / 20.0) as usize) + (width + x + f32::floor(latitude_modifier_2 * width as f32 / 40.0) as usize) % width; let offset_cell_x_2 = - (width + x + f32::floor(latitude_modifier_2 * width as f32 / 15.0) as usize) + (width + x + f32::floor(latitude_modifier_2 * width as f32 / 20.0) as usize) % width; let offset_cell_x_3 = (width + x + f32::floor(latitude_modifier_2 * width as f32 / 10.0) as usize) @@ -540,7 +532,7 @@ impl World { - (offset_altitude_3 * 0.5) - (offset_altitude_4 * 0.4) - (offset_altitude_5 * 0.5) - + (World::MAX_ALTITUDE * 0.18 * random_noise_2) + + (World::MAX_ALTITUDE * 0.17 * random_noise_2) - (altitude_value * 0.25)) / World::MAX_ALTITUDE; @@ -734,9 +726,12 @@ impl World { } #[must_use] - pub fn cell_neighbors(&self, x: usize, y: usize) -> HashMap { + pub fn cell_neighbors(&self, x: u32, y: u32) -> HashMap { let mut neighbors = HashMap::new(); + let x = x as usize; + let y = y as usize; + let height = self.height as usize; let width = self.width as usize; @@ -910,6 +905,63 @@ impl World { } return false; } + + fn set_initial_human_groups(&mut self, progress_sender: &Sender<(f32, String)>) -> () { + const MAX_GROUPS: u8 = 5; + const MINIMUM_PRESENCE: f32 = 0.1; + + let mut placed_groups = 0; + let mut tries = 0; + while placed_groups < MAX_GROUPS { + tries += 1; + send_progress( + progress_sender, + placed_groups as f32 / MAX_GROUPS as f32, + format!("Placing initial population: {placed_groups}/{MAX_GROUPS} (try #{tries})"), + ); + + let x = self.rng.gen_range(0..self.width as usize); + let y = self.rng.gen_range(0..self.height as usize); + + let grassland_presence = self.terrain[y][x].biome_presence(BiomeType::Grassland); + + match grassland_presence { + Some(presence) => { + if presence < MINIMUM_PRESENCE { + continue; + } + }, + None => continue, + } + + let new_human_group = Arc::new(HumanGroup { + id: placed_groups as u32, + population: 1000, + }); + + self.human_groups_to_update + .push(Arc::::downgrade(&new_human_group)); + self.terrain[y][x].human_groups.push(new_human_group); + + placed_groups += 1; + tries = 0; + } + } + + pub fn iterate(&mut self) { + for group in self.human_groups_to_update.iter() { + if let Some(group) = group.upgrade() { + group.update(self); + } + } + self.human_groups_to_update.clear(); + self.iteration += 1; + } + + #[inline(always)] + pub fn add_human_group_to_update(&mut self, group: Weak) { + self.human_groups_to_update.push(group); + } } fn send_progress>( diff --git a/planet/src/world_manager.rs b/planet/src/world_manager.rs index 28f3921..1f37c7e 100644 --- a/planet/src/world_manager.rs +++ b/planet/src/world_manager.rs @@ -1,3 +1,5 @@ +use std::io::{Write, BufReader}; + use { crate::{World, WorldGenError}, bevy::{ @@ -12,7 +14,7 @@ use { error::Error, fmt::Display, fs::File, - io::{self, Read, Write}, + io::{self, BufWriter}, path::Path, }, }; @@ -20,7 +22,7 @@ use { #[derive(Debug)] pub enum LoadError { MissingSave(io::Error), - InvalidSave(postcard::Error), + InvalidSave(bincode::Error), } impl Error for LoadError { fn source(&self) -> Option<&(dyn Error + 'static)> { @@ -29,15 +31,8 @@ impl Error for LoadError { LoadError::InvalidSave(error) => Some(error), } } - - fn description(&self) -> &str { - "description() is deprecated; use Display" - } - - fn cause(&self) -> Option<&dyn Error> { - self.source() - } } + impl Display for LoadError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { @@ -53,7 +48,7 @@ impl Display for LoadError { #[derive(Debug)] pub enum SaveError { MissingWorld, - SerializationError(postcard::Error), + SerializationError(bincode::Error), FailedToWrite(io::Error), } impl Error for SaveError { @@ -103,32 +98,31 @@ impl WorldManager { return Err(SaveError::MissingWorld); }; - let serialized = match postcard::to_stdvec(world) { - Ok(serialized) => serialized, - Err(err) => { - return Err(SaveError::SerializationError(err)); - }, + let save_file = match File::create(path) { + Ok(save_file) => save_file, + Err(err) => return Err(SaveError::FailedToWrite(err)), }; - match File::create(path).unwrap().write_all(serialized.as_slice()) { + let serialized = match bincode::serialize(world) { + Ok(serialized) => serialized, + Err(err) => return Err(SaveError::SerializationError(err)), + }; + + match BufWriter::new(save_file).write(serialized.as_slice()) { Ok(_) => Ok(()), Err(err) => Err(SaveError::FailedToWrite(err)), } } pub fn load_world>(&mut self, path: P) -> Result<(), LoadError> { - let mut file = match File::open(path) { + let file = match File::open(path) { Ok(file) => file, Err(err) => { return Err(LoadError::MissingSave(err)); }, }; - let mut buf = vec![]; - if let Err(err) = file.read_to_end(&mut buf) { - return Err(LoadError::MissingSave(err)); - }; - - match postcard::from_bytes(buf.as_slice()) { + + match bincode::deserialize_from(BufReader::new(file)) { Ok(world) => { self.world = Some(world); Ok(()) @@ -142,6 +136,11 @@ impl WorldManager { self.world.as_ref() } + #[must_use] + pub fn get_world_mut(&mut self) -> Option<&mut World> { + self.world.as_mut() + } + pub fn set_world(&mut self, world: World) { self.world = Some(world); } @@ -153,7 +152,7 @@ impl WorldManager { ) -> Task> { AsyncComputeTaskPool::get().spawn(async move { let seed = seed.unwrap_or_else(random); - let mut new_world = World::async_new( + let mut new_world = World::new( WorldManager::NEW_WORLD_WIDTH, WorldManager::NEW_WORLD_HEIGHT, seed, diff --git a/src/gui/windows/tile_info.rs b/src/gui/windows/tile_info.rs index d9328c0..9657aee 100644 --- a/src/gui/windows/tile_info.rs +++ b/src/gui/windows/tile_info.rs @@ -44,6 +44,9 @@ impl WindowSystem for TileInfo<'_, '_> { .. } = &world.terrain[cursor_y as usize][cursor_x as usize]; + _ = ui.label("Iteration"); + _ = ui.label(format!("{}", world.iteration)); + ui.end_row(); _ = ui.label("Coordinates"); _ = ui.label(format!("{x}:{y}")); ui.end_row(); diff --git a/src/main.rs b/src/main.rs index 9711449..8ba2464 100644 --- a/src/main.rs +++ b/src/main.rs @@ -232,11 +232,11 @@ fn update_gui(world: &mut World) { #[cfg(feature = "render")] fn redraw_map( mut should_redraw: ResMut, - world_manager: Res, mut world_renderer: ResMut, - render_settings: Res, mut images: ResMut>, mut map_sprite: Query<&mut Sprite>, + render_settings: Res, + world_manager: Res, ) { let Some(world) = world_manager.get_world() else { #[cfg(feature = "logging")] @@ -278,6 +278,12 @@ fn redraw_map( } } +fn iterate_world(mut world_manager: ResMut) { + if let Some(world) = world_manager.get_world_mut() { + world.iterate(); + }; +} + #[cfg(feature = "render")] const WORLD_SCALE: i32 = 4; fn main() -> Result<(), Box> { @@ -303,7 +309,8 @@ fn main() -> Result<(), Box> { .add_system(update_gui) .add_system(update_cursor_map_position) .add_system(open_tile_info) - .add_system(redraw_map); + .add_system(redraw_map) + .add_system(iterate_world); app.add_plugins(WorldPlugins); } diff --git a/src/planet_renderer.rs b/src/planet_renderer.rs index cb0a5ec..640d141 100644 --- a/src/planet_renderer.rs +++ b/src/planet_renderer.rs @@ -39,13 +39,13 @@ impl WorldRenderSettings { pub fn toggle_overlay(&mut self, overlay: &WorldOverlay) { if self.visible_overlays.contains(overlay) { assert!( - self.visible_overlays.remove(overlay), - "Failed to remove overlay [{overlay:#?}], that shouldn't happen." + self.visible_overlays.remove(overlay), + "Failed to remove overlay [{overlay:#?}], that shouldn't happen." ); } else { assert!( - self.visible_overlays.insert(*overlay), - "Failed to insert overlay [{overlay:#?}], that shouldn't happen." + self.visible_overlays.insert(*overlay), + "Failed to insert overlay [{overlay:#?}], that shouldn't happen." ); } } @@ -53,38 +53,25 @@ impl WorldRenderSettings { #[must_use] fn population_color(world: &World, cell: &TerrainCell) -> Color { - let slant = world.get_slant(cell); - let altitude_difference = world.max_altitude - world.min_altitude; + let cell_population = cell + .human_groups + .iter() + .map(|group| group.population) + .sum::(); - let slant_factor = f32::min(1.0, (4.0 + (10.0 * slant / altitude_difference)) / 5.0); - - let altitude_factor = f32::min(1.0, (0.5 + ((cell.altitude - altitude_difference) / altitude_difference)) / 1.5); - - let mut total_population = 0; - - for human_group in cell.human_groups { - total_population += human_group.population; - } - - let color = if total_population > 0 { + if cell_population > 0 { + debug!(cell.x, cell.y, "Population present"); Color::GREEN } else { let color = biome_color(world, cell); - let greyscale = (color.r() + color.g() + color.b()) / 4.5 + 0.25; + let grey = color.r() + color.g() + color.b(); + let r = (color.r() + grey) / 6.0; + let g = (color.g() + grey) / 6.0; + let b = (color.b() + grey) / 6.0; - color.set_r(greyscale); - color.set_g(greyscale); - color.set_b(greyscale); - - color - }; - - let r = color.r() * slant_factor * altitude_factor; - let g = color.g() * slant_factor * altitude_factor; - let b = color.b() * slant_factor * altitude_factor; - - Color::rgb(r, g, b) + Color::rgb(r, g, b) + } } #[must_use] @@ -221,6 +208,7 @@ impl WorldRenderer { WorldView::Biomes => 0, WorldView::Topography => 1, WorldView::Coastlines => 2, + WorldView::Population => 3, }; let mut overlay_num = 0; for overlay in render_settings.visible_overlays.iter() { @@ -292,6 +280,7 @@ impl WorldRenderer { WorldView::Biomes => biome_color(world, cell), WorldView::Topography => altitude_contour_color(world, cell.altitude), WorldView::Coastlines => coastline_color(world, cell), + WorldView::Population => population_color(world, cell), }; let mut normalizer = 1.0;