Tweak some more, idk what else to say, not like I understand this.

Population is next

7d5d16bde5fd3e50bb6e5faf934db32415ef6626
149fbe66d2903c9ad4005977973ee53583b97430
a979a07249a0b0eed797ab365bc88cd7c74672e1
8a81ec053123cc2e6fd69b4b7bae6d7b39c75e63
This commit is contained in:
Tobias Berger 2022-11-20 19:47:23 +01:00
parent cb935618b0
commit af05c1b761
Signed by: toby
GPG key ID: 2D05EFAB764D6A88
9 changed files with 236 additions and 74 deletions

View file

@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct HumanGroup {
pub id: u32,
pub population: u32,
}

View file

@ -1,3 +1,4 @@
pub mod human_group;
pub mod world; pub mod world;
pub use world::{TerrainCell, World, WorldGenError}; pub use world::{TerrainCell, World, WorldGenError};
pub mod biome; pub mod biome;

View file

@ -1,4 +1,17 @@
const PERMUTATION: [u8; 256] = [ const PERMUTATION: [u8; 512] = [
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69,
142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219,
203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230,
220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76,
132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173,
186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206,
59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163,
70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232,
178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162,
241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204,
176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141,
128, 195, 78, 66, 215, 61, 156, 180, // Duplicated
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69,
142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219,
203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
@ -15,9 +28,28 @@ const PERMUTATION: [u8; 256] = [
]; ];
#[must_use] #[must_use]
pub fn perlin_value(x: f32, y: f32, z: f32) -> f32 { pub fn permutation_value(x: f32, y: f32, z: f32) -> u32 {
let p = [PERMUTATION, PERMUTATION].concat(); let x = (f32::floor(x) as i32 & 255) as usize;
let y = (f32::floor(y) as i32 & 255) as usize;
let z = (f32::floor(z) as i32 & 255) as usize;
let a = PERMUTATION[x] as usize + y;
let aa = PERMUTATION[a] as usize + z;
let ab = PERMUTATION[aa] as u32;
let b = PERMUTATION[x + 1] as usize + y;
let ba = PERMUTATION[b] as usize + z;
let bb = PERMUTATION[ba] as u32;
let c = PERMUTATION[x + 2] as usize + y;
let ca = PERMUTATION[c] as usize + z;
let cb = PERMUTATION[ca] as u32;
ab + (bb * 256) + (cb * 256 * 256)
}
#[must_use]
pub fn perlin_value(x: f32, y: f32, z: f32) -> f32 {
let fx: i32 = f32::floor(x) as i32; let fx: i32 = f32::floor(x) as i32;
let fy: i32 = f32::floor(y) as i32; let fy: i32 = f32::floor(y) as i32;
let fz: i32 = f32::floor(z) as i32; let fz: i32 = f32::floor(z) as i32;
@ -34,36 +66,40 @@ pub fn perlin_value(x: f32, y: f32, z: f32) -> f32 {
let v = fade(y); let v = fade(y);
let w = fade(z); let w = fade(z);
let a = p[xb] as usize + yb; let a = PERMUTATION[xb] as usize + yb;
let aa = p[a] as usize + zb; let aa = PERMUTATION[a] as usize + zb;
let ab = p[a + 1] as usize + zb; let ab = PERMUTATION[a + 1] as usize + zb;
let b = p[xb + 1] as usize + yb; let b = PERMUTATION[xb + 1] as usize + yb;
let ba = p[b] as usize + zb; let ba = PERMUTATION[b] as usize + zb;
let bb = p[b + 1] as usize + zb; let bb = PERMUTATION[b + 1] as usize + zb;
scale(lerp( scale(lerp(
w, w,
lerp( lerp(
v, v,
lerp(u, grad(p[aa], x, y, z), grad(p[ba], x - 1.0, y, z)),
lerp( lerp(
u, u,
grad(p[ab], x, y - 1.0, z), grad(PERMUTATION[aa], x, y, z),
grad(p[bb], x - 1.0, y - 1.0, z), grad(PERMUTATION[ba], x - 1.0, y, z),
),
lerp(
u,
grad(PERMUTATION[ab], x, y - 1.0, z),
grad(PERMUTATION[bb], x - 1.0, y - 1.0, z),
), ),
), ),
lerp( lerp(
v, v,
lerp( lerp(
u, u,
grad(p[aa + 1], x, y, z - 1.0), grad(PERMUTATION[aa + 1], x, y, z - 1.0),
grad(p[ba + 1], x - 1.0, y, z - 1.0), grad(PERMUTATION[ba + 1], x - 1.0, y, z - 1.0),
), ),
lerp( lerp(
u, u,
grad(p[ab + 1], x, y - 1.0, z - 1.0), grad(PERMUTATION[ab + 1], x, y - 1.0, z - 1.0),
grad(p[bb + 1], x - 1.0, y - 1.0, z - 1.0), grad(PERMUTATION[bb + 1], x - 1.0, y - 1.0, z - 1.0),
), ),
), ),
)) ))

2
planet/src/saving/mod.rs Normal file
View file

@ -0,0 +1,2 @@
// pub mod terrain_cell;
pub mod world;

View file

@ -1,5 +1,6 @@
use { use {
crate::{TerrainCell, World}, crate::{TerrainCell, World},
bevy::prelude::debug,
rand::{rngs::StdRng, SeedableRng}, rand::{rngs::StdRng, SeedableRng},
serde::{ serde::{
de::{Error, MapAccess, SeqAccess, Visitor}, de::{Error, MapAccess, SeqAccess, Visitor},
@ -43,6 +44,7 @@ impl<'de> Deserialize<'de> for World {
Terrain, Terrain,
ContinentOffsets, ContinentOffsets,
ContinentSizes, ContinentSizes,
Iteration,
} }
struct WorldVisitor; struct WorldVisitor;
@ -64,23 +66,29 @@ impl<'de> Deserialize<'de> for World {
let height = seq let height = seq
.next_element()? .next_element()?
.ok_or_else(|| Error::invalid_length(0, &self))?; .ok_or_else(|| Error::invalid_length(1, &self))?;
let seed = seq let seed = seq
.next_element()? .next_element()?
.ok_or_else(|| Error::invalid_length(0, &self))?; .ok_or_else(|| Error::invalid_length(2, &self))?;
let terrain: Vec<Vec<TerrainCell>> = seq let terrain: Vec<Vec<TerrainCell>> = seq
.next_element()? .next_element()?
.ok_or_else(|| Error::invalid_length(0, &self))?; .ok_or_else(|| Error::invalid_length(3, &self))?;
let continent_offsets = seq let continent_offsets = seq
.next_element()? .next_element()?
.ok_or_else(|| Error::invalid_length(0, &self))?; .ok_or_else(|| Error::invalid_length(4, &self))?;
let continent_widths = seq let continent_sizes = seq
.next_element()? .next_element()?
.ok_or_else(|| Error::invalid_length(0, &self))?; .ok_or_else(|| Error::invalid_length(5, &self))?;
debug!("Iteration aaaaa");
let iteration = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(6, &self))?;
debug!("Iteration bbbbb");
let world_attributes = &mut WorldTerrainAttributes::default(); let world_attributes = &mut WorldTerrainAttributes::default();
let world_attributes = let world_attributes =
@ -111,13 +119,14 @@ impl<'de> Deserialize<'de> for World {
attributes attributes
}); });
Ok(World { debug!("Constructing world");
let mut world = World {
width, width,
height, height,
seed, seed,
terrain, terrain,
continent_offsets, continent_offsets,
continent_sizes: continent_widths, continent_sizes,
max_altitude: world_attributes.max_altitude, max_altitude: world_attributes.max_altitude,
min_altitude: world_attributes.min_altitude, min_altitude: world_attributes.min_altitude,
@ -127,7 +136,22 @@ impl<'de> Deserialize<'de> for World {
min_temperature: world_attributes.min_temperature, min_temperature: world_attributes.min_temperature,
rng: StdRng::seed_from_u64(seed as u64), rng: StdRng::seed_from_u64(seed as u64),
}) iteration,
};
{
let mut y = 0;
debug!("Completing terrain");
for terrain_row in world.terrain.iter_mut() {
let mut x = 0;
for terrain_cell in terrain_row.iter_mut() {
terrain_cell.x = x;
terrain_cell.y = y;
x += 1;
}
y += 1;
}
}
Ok(world)
} }
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error> fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
@ -140,6 +164,7 @@ impl<'de> Deserialize<'de> for World {
let mut terrain = None; let mut terrain = None;
let mut continent_offsets = None; let mut continent_offsets = None;
let mut continent_widths = None; let mut continent_widths = None;
let mut iteration = None;
while let Some(key) = map.next_key()? { while let Some(key) = map.next_key()? {
match key { match key {
@ -179,6 +204,12 @@ impl<'de> Deserialize<'de> for World {
} }
continent_widths = Some(map.next_value()?); continent_widths = Some(map.next_value()?);
}, },
Field::Iteration => {
if iteration.is_some() {
return Err(Error::duplicate_field("iteration"));
}
iteration = Some(map.next_value()?);
},
} }
} }
@ -229,7 +260,9 @@ impl<'de> Deserialize<'de> for World {
attributes attributes
}); });
Ok(World { let iteration = iteration.ok_or_else(|| Error::missing_field("iteration"))?;
let mut world = World {
width, width,
height, height,
seed, seed,
@ -245,7 +278,21 @@ impl<'de> Deserialize<'de> for World {
min_temperature: world_attributes.min_temperature, min_temperature: world_attributes.min_temperature,
rng: StdRng::seed_from_u64(seed as u64), rng: StdRng::seed_from_u64(seed as u64),
}) iteration,
};
{
let mut y = 0;
for terrain_row in world.terrain.iter_mut() {
let mut x = 0;
for terrain_cell in terrain_row.iter_mut() {
terrain_cell.x = x;
terrain_cell.y = y;
x += 1;
}
y += 1;
}
}
Ok(world)
} }
} }

View file

@ -89,6 +89,7 @@ pub struct World {
pub min_temperature: f32, pub min_temperature: f32,
#[serde(skip)] #[serde(skip)]
pub rng: StdRng, pub rng: StdRng,
pub iteration: usize,
} }
#[derive(Debug, Clone, Default, Deserialize, Serialize)] #[derive(Debug, Clone, Default, Deserialize, Serialize)]
@ -98,24 +99,40 @@ pub struct TerrainCell {
pub temperature: f32, pub temperature: f32,
#[serde(skip)] #[serde(skip)]
pub x: usize, pub x: usize,
#[serde(skip)] #[serde(skip)]
pub y: usize, pub y: usize,
pub local_iteration: usize,
pub biome_presences: Vec<(BiomeType, f32)>, pub biome_presences: Vec<(BiomeType, f32)>,
} }
impl TerrainCell {
pub fn get_next_local_random_int(&mut self, world: &World) -> f32 {
let seed = world.seed;
let x = seed as f32 + self.x as f32;
let y = seed as f32 + self.y as f32;
let z = seed as f32 + world.iteration as f32 + (self.local_iteration - 1) as f32;
drop(world);
self.local_iteration += 1;
perlin::perlin_value(x, y, z)
}
}
impl World { impl World {
pub const ALTITUDE_SPAN: f32 = World::MAX_ALTITUDE - World::MIN_ALTITUDE; pub const ALTITUDE_SPAN: f32 = World::MAX_ALTITUDE - World::MIN_ALTITUDE;
pub const CONTINENT_MAX_SIZE_FACTOR: f32 = 8.0; pub const CONTINENT_MAX_SIZE_FACTOR: f32 = 8.7;
pub const CONTINENT_MIN_SIZE_FACTOR: f32 = 6.0; pub const CONTINENT_MIN_SIZE_FACTOR: f32 = 5.7;
pub const MAX_ALTITUDE: f32 = 15000.0; pub const MAX_ALTITUDE: f32 = 15000.0;
pub const MAX_RAINFALL: f32 = 13000.0; pub const MAX_RAINFALL: f32 = 13000.0;
pub const MAX_TEMPERATURE: f32 = 30.0; pub const MAX_TEMPERATURE: f32 = 30.0;
pub const MIN_ALTITUDE: f32 = -15000.0; pub const MIN_ALTITUDE: f32 = -15000.0;
pub const MIN_RAINFALL: f32 = 0.0; pub const MIN_RAINFALL: f32 = 0.0;
pub const MIN_TEMPERATURE: f32 = -35.0; pub const MIN_TEMPERATURE: f32 = -35.0;
pub const NUM_CONTINENTS: u8 = 6; pub const NUM_CONTINENTS: u8 = 12;
pub const RAINFALL_DRYNESS_FACTOR: f32 = 0.005; pub const RAINFALL_DRYNESS_FACTOR: f32 = 0.005;
pub const RAINFALL_DRYNESS_OFFSET: f32 = World::RAINFALL_DRYNESS_FACTOR * World::MAX_RAINFALL; pub const RAINFALL_DRYNESS_OFFSET: f32 = World::RAINFALL_DRYNESS_FACTOR * World::MAX_RAINFALL;
pub const RAINFALL_SPAN: f32 = World::MAX_RAINFALL - World::MIN_RAINFALL; pub const RAINFALL_SPAN: f32 = World::MAX_RAINFALL - World::MIN_RAINFALL;
@ -127,10 +144,7 @@ impl World {
width, width,
height, height,
seed, seed,
terrain: vec![ terrain: vec![vec![default(); width.try_into().unwrap()]; height.try_into().unwrap()],
vec![TerrainCell::default(); width.try_into().unwrap()];
height.try_into().unwrap()
],
continent_offsets: [default(); World::NUM_CONTINENTS as usize], continent_offsets: [default(); World::NUM_CONTINENTS as usize],
continent_sizes: [default(); World::NUM_CONTINENTS as usize], continent_sizes: [default(); World::NUM_CONTINENTS as usize],
max_altitude: World::MIN_ALTITUDE, max_altitude: World::MIN_ALTITUDE,
@ -140,6 +154,7 @@ impl World {
max_temperature: World::MIN_TEMPERATURE, max_temperature: World::MIN_TEMPERATURE,
min_temperature: World::MAX_TEMPERATURE, min_temperature: World::MAX_TEMPERATURE,
rng: StdRng::seed_from_u64(seed as u64), rng: StdRng::seed_from_u64(seed as u64),
iteration: 0,
} }
} }
@ -148,10 +163,7 @@ impl World {
width, width,
height, height,
seed, seed,
terrain: vec![ terrain: vec![vec![default(); width.try_into().unwrap()]; height.try_into().unwrap()],
vec![TerrainCell::default(); width.try_into().unwrap()];
height.try_into().unwrap()
],
continent_offsets: [default(); World::NUM_CONTINENTS as usize], continent_offsets: [default(); World::NUM_CONTINENTS as usize],
continent_sizes: [default(); World::NUM_CONTINENTS as usize], continent_sizes: [default(); World::NUM_CONTINENTS as usize],
max_altitude: World::MIN_ALTITUDE, max_altitude: World::MIN_ALTITUDE,
@ -161,6 +173,7 @@ impl World {
max_temperature: World::MIN_TEMPERATURE, max_temperature: World::MIN_TEMPERATURE,
min_temperature: World::MAX_TEMPERATURE, min_temperature: World::MAX_TEMPERATURE,
rng: StdRng::seed_from_u64(seed as u64), rng: StdRng::seed_from_u64(seed as u64),
iteration: 0,
} }
} }
@ -187,35 +200,76 @@ impl World {
Ok(()) Ok(())
} }
fn generate_continents(&mut self) { fn generate_continents(&mut self, progress_sender: &Sender<(f32, String)>) {
#[cfg(feature = "logging")]
info!("Generating continents"); info!("Generating continents");
send_progress(progress_sender, 0.0, format!("Generating continents"));
let width = self.width as f32; let width = self.width as f32;
let height = self.height as f32; let height = self.height as f32;
const LONGTITUDE_FACTOR: f32 = 15.0;
const LATITUDE_FACTOR: f32 = 6.0; const LATITUDE_FACTOR: f32 = 6.0;
for i in 0..World::NUM_CONTINENTS { let mut previous_position = Vec2 {
// #[cfg(feature = "logging")] x: self
// info!("Continents: {}/{}", i, World::NUM_CONTINENTS);
self.continent_offsets[i as usize].x = self
.rng .rng
.gen_range(width * i as f32 * 2.0 / 5.0..(width * (i as f32 + 2.0) * 2.0 / 5.0)) .gen_range(0.0..width * (LONGTITUDE_FACTOR - 1.0) / LONGTITUDE_FACTOR),
.repeat(width); y: self.rng.gen_range(
self.continent_offsets[i as usize].y = self.rng.gen_range( height / LATITUDE_FACTOR..height * (LATITUDE_FACTOR - 1.0) / LATITUDE_FACTOR,
height * 1.0 / LATITUDE_FACTOR..height * (LATITUDE_FACTOR - 1.0) / LATITUDE_FACTOR, ),
};
for i in 0..World::NUM_CONTINENTS {
send_progress(
progress_sender,
i as f32 / World::NUM_CONTINENTS as f32,
format!("Generating continents: {i}/{{World::NUM_CONTINENTS}}"),
);
let idx = i as usize;
let width_offset = self.rng.gen_range(0.0..6.0);
self.continent_offsets[idx] = previous_position;
self.continent_sizes[idx] = Vec2 {
x: self.rng.gen_range(
World::CONTINENT_MIN_SIZE_FACTOR + width_offset
..World::CONTINENT_MAX_SIZE_FACTOR + width_offset,
),
y: self.rng.gen_range(
World::CONTINENT_MIN_SIZE_FACTOR + width_offset
..World::CONTINENT_MAX_SIZE_FACTOR + width_offset,
),
};
let y_position = self.rng.gen_range(
height / LATITUDE_FACTOR..height * (LATITUDE_FACTOR - 1.0) / LATITUDE_FACTOR,
); );
self.continent_sizes[i as usize] = Vec2 { let new_vector = if i % 3 == 2 {
x: self Vec2 {
.rng x: f32::repeat(
.gen_range(World::CONTINENT_MIN_SIZE_FACTOR..World::CONTINENT_MAX_SIZE_FACTOR), previous_position.x
y: self + self.rng.gen_range(
.rng width * 4.0 / LONGTITUDE_FACTOR..width * 6.0 / LONGTITUDE_FACTOR,
.gen_range(World::CONTINENT_MIN_SIZE_FACTOR..World::CONTINENT_MAX_SIZE_FACTOR) ),
/ 2.0, width,
),
y: y_position,
}
} else {
Vec2 {
x: f32::repeat(
previous_position.x
+ self.rng.gen_range(
width / LONGTITUDE_FACTOR..width * 2.0 / LONGTITUDE_FACTOR,
),
width,
),
y: y_position,
}
}; };
previous_position = new_vector;
} }
info!("Done generating continents"); info!("Done generating continents");
} }
@ -278,16 +332,16 @@ impl World {
progress_sender: &Sender<(f32, String)>, progress_sender: &Sender<(f32, String)>,
) -> Result<(), CartesianError> { ) -> Result<(), CartesianError> {
info!("Generating altitude"); info!("Generating altitude");
self.generate_continents(); self.generate_continents(progress_sender);
const RADIUS_1: f32 = 0.5; const RADIUS_1: f32 = 0.75;
const RADIUS_2: f32 = 8.0; const RADIUS_2: f32 = 8.0;
const RADIUS_3: f32 = 4.0; const RADIUS_3: f32 = 4.0;
const RADIUS_4: f32 = 8.0; const RADIUS_4: f32 = 8.0;
const RADIUS_5: f32 = 16.0; const RADIUS_5: f32 = 16.0;
const RADIUS_6: f32 = 64.0; const RADIUS_6: f32 = 64.0;
const RADIUS_7: f32 = 128.0; const RADIUS_7: f32 = 128.0;
const RADIUS_8: f32 = 1.0; const RADIUS_8: f32 = 1.5;
const RADIUS_9: f32 = 1.0; const RADIUS_9: f32 = 1.0;
let offset_1 = World::random_offset_vector(&mut self.rng); let offset_1 = World::random_offset_vector(&mut self.rng);
@ -433,8 +487,10 @@ impl World {
info!("Generating rainfall"); info!("Generating rainfall");
const RADIUS_1: f32 = 2.0; const RADIUS_1: f32 = 2.0;
const RADIUS_2: f32 = 1.0; const RADIUS_2: f32 = 1.0;
const RADIUS_3: f32 = 16.0;
let offset_1 = World::random_offset_vector(&mut self.rng); let offset_1 = World::random_offset_vector(&mut self.rng);
let offset_2 = World::random_offset_vector(&mut self.rng); let offset_2 = World::random_offset_vector(&mut self.rng);
let offset_3 = World::random_offset_vector(&mut self.rng);
let height = self.terrain.len(); let height = self.terrain.len();
for y in 0..height { for y in 0..height {
@ -457,8 +513,12 @@ impl World {
.random_noise_from_polar_coordinates(alpha, beta, RADIUS_2, offset_2)? .random_noise_from_polar_coordinates(alpha, beta, RADIUS_2, offset_2)?
* 1.5 * 1.5
+ 0.25; + 0.25;
let random_noise_3 =
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_3, offset_3)?;
let latitude_factor = alpha + (random_noise_1 * 2.0 - 1.0) * PI * 0.2; let value_a = mix_values(random_noise_1, random_noise_3, 0.15);
let latitude_factor = alpha + (value_a * 2.0 - 1.0) * PI * 0.2;
let latitude_modifier_1 = (1.5 * f32::sin(latitude_factor)) - 0.5; let latitude_modifier_1 = (1.5 * f32::sin(latitude_factor)) - 0.5;
let latitude_modifier_2 = f32::cos(latitude_factor); let latitude_modifier_2 = f32::cos(latitude_factor);
@ -545,8 +605,10 @@ impl World {
progress_sender: &Sender<(f32, String)>, progress_sender: &Sender<(f32, String)>,
) -> Result<(), CartesianError> { ) -> Result<(), CartesianError> {
info!("Generating temperature"); info!("Generating temperature");
let offset = World::random_offset_vector(&mut self.rng); let offset_1 = World::random_offset_vector(&mut self.rng);
const RADIUS: f32 = 2.0; let offset_2 = World::random_offset_vector(&mut self.rng);
const RADIUS_1: f32 = 2.0;
const RADIUS_2: f32 = 16.0;
let height = self.terrain.len(); let height = self.terrain.len();
for y in 0..height { for y in 0..height {
@ -564,12 +626,14 @@ impl World {
let beta = (x as f32 / self.width as f32) * TAU; let beta = (x as f32 / self.width as f32) * TAU;
let random_noise = let random_noise_1 =
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS, offset)?; self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_1, offset_1)?;
let random_noise_2 =
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_2, offset_2)?;
let cell = &mut self.terrain[y][x]; let cell = &mut self.terrain[y][x];
let latitude_modifer = mix_values(alpha, random_noise * PI, 0.1); let latitude_modifer = alpha * 0.9 + (random_noise_1 + random_noise_2) * 0.05 * PI;
let altitude_factor = f32::max( let altitude_factor = f32::max(
0.0, 0.0,
(cell.altitude / World::MAX_ALTITUDE) * World::TEMPERATURE_ALTITUDE_FACTOR, (cell.altitude / World::MAX_ALTITUDE) * World::TEMPERATURE_ALTITUDE_FACTOR,

View file

@ -42,7 +42,10 @@ impl Display for LoadError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self { match self {
LoadError::MissingSave(_) => f.write_str("No save found at given path"), LoadError::MissingSave(_) => f.write_str("No save found at given path"),
LoadError::InvalidSave(_) => f.write_str("Loaded file is not a valid save"), LoadError::InvalidSave(err) => f.write_fmt(format_args!(
"Loaded file is not a valid save - {}",
err.to_string()
)),
} }
} }
} }

View file

@ -31,12 +31,12 @@ impl WindowSystem for SaveLoad<'_, '_> {
if let Some(path) = tinyfiledialogs::save_file_dialog_with_filter( if let Some(path) = tinyfiledialogs::save_file_dialog_with_filter(
"Save world", "Save world",
state.file_name.as_str(), state.file_name.as_str(),
&["*.rsplnt", "*.ron"], &["*.rsplnt", "*.rsplnt"],
"World file", "World file",
) { ) {
if let Err(err) = world_manager.save_world(&path) { if let Err(err) = world_manager.save_world(&path) {
// TODO: Error popup // TODO: Error popup
error!("Failed to save: {err:#?}"); error!("Failed to save: {err}");
} }
*state.file_name = path; *state.file_name = path;
} }
@ -45,14 +45,15 @@ impl WindowSystem for SaveLoad<'_, '_> {
if let Some(path) = tinyfiledialogs::open_file_dialog( if let Some(path) = tinyfiledialogs::open_file_dialog(
"World file", "World file",
state.file_name.as_str(), state.file_name.as_str(),
Some((&["*.ron", "*.rsplnt"], "*.ron,*.rsplnt")), Some((&["*.rsplnt"], "*.rspnt")),
) { ) {
if let Err(err) = world_manager.load_world(&path) { if let Err(err) = world_manager.load_world(&path) {
// TODO: Error popup // TODO: Error popup
error!("Failed to load: {err:#?}"); error!("Failed to load: {err}");
} else {
should_redraw.0 = true;
} }
*state.file_name = path; *state.file_name = path;
should_redraw.0 = true;
} }
} }
}); });

View file

@ -41,6 +41,7 @@ impl WindowSystem for TileInfo<'_, '_> {
biome_presences, biome_presences,
x, x,
y, y,
..
} = &world.terrain[cursor_y as usize][cursor_x as usize]; } = &world.terrain[cursor_y as usize][cursor_x as usize];
_ = ui.label("Coordinates"); _ = ui.label("Coordinates");