use fastnoise_lite::{FastNoiseLite, NoiseType}; use glam::{IVec2, Vec2}; use crate::{ config::CHUNK_SIZE, content::materials::MaterialId, sim::{cell::Cell, cell_manager::chunk::Chunk}, }; #[derive(Clone, Copy)] pub struct WorldGeneratorConfig { pub occupied_threshold: f32, pub stone_threshold: f32, pub proc_gen_seed: i32, pub cave_noise_freq: f32, pub cave_noise_type: NoiseType, pub hardness_noise_freq: f32, pub hardness_noise_type: NoiseType, } impl Default for WorldGeneratorConfig { fn default() -> Self { Self { occupied_threshold: 0.05, stone_threshold: 0.6, proc_gen_seed: 10, cave_noise_freq: 0.005, cave_noise_type: NoiseType::OpenSimplex2S, hardness_noise_freq: 0.015, hardness_noise_type: NoiseType::OpenSimplex2S, } } } pub struct WorldGenerator { config: WorldGeneratorConfig, cave_noise: Option, hardness_noise: Option, } impl WorldGenerator { pub fn generate_chunk(&mut self, chunk_position: IVec2) -> Chunk { if let Some(cave_noise) = &self.cave_noise && let Some(hardness_noise) = &self.hardness_noise { let mut c = Chunk::void(); let position = chunk_position * CHUNK_SIZE; for x in 0..CHUNK_SIZE { for y in 0..CHUNK_SIZE { let cell_position = position.as_vec2() + Vec2::new(x as f32, y as f32); let cnv = cave_noise.get_noise_2d(cell_position.x, cell_position.y); let hnv = hardness_noise.get_noise_2d(cell_position.x, cell_position.y); let occupied = cnv < self.config.occupied_threshold; if occupied { let material = if hnv > self.config.stone_threshold { MaterialId::Stone } else { MaterialId::Dirt }; c.set_cell_at_local_position( x as u8, y as u8, Cell::from_material(material), ); } } } c } else { panic!("Call update_params first"); } } pub fn update_params(&mut self, config: WorldGeneratorConfig) { let mut cave_noise = FastNoiseLite::with_seed(config.proc_gen_seed + 50); cave_noise.set_frequency(Some(config.cave_noise_freq)); cave_noise.set_noise_type(Some(config.cave_noise_type)); let mut hardness_noise = FastNoiseLite::with_seed(config.proc_gen_seed + 100); hardness_noise.set_frequency(Some(config.hardness_noise_freq)); hardness_noise.set_noise_type(Some(config.hardness_noise_type)); self.cave_noise = Some(cave_noise); self.hardness_noise = Some(hardness_noise); self.config = config; } pub fn new(config: WorldGeneratorConfig) -> Self { let mut wg = WorldGenerator { config, cave_noise: None, hardness_noise: None, }; wg.update_params(config); wg } }