diff --git a/Cargo.lock b/Cargo.lock index aad7944..0deef6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -546,6 +546,7 @@ dependencies = [ "s2dc", "sfml", "sfml-xt", + "worldgen", ] [[package]] @@ -1159,3 +1160,9 @@ checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" dependencies = [ "memchr", ] + +[[package]] +name = "worldgen" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b77fba24c873b60af296c1f0c5639114186d1ac3c99f880a7bb590bdc04065" diff --git a/Cargo.toml b/Cargo.toml index 2d562a7..63ce3d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ hecs = "0.10.1" rand = "0.8.5" rfd = "0.11.3" sfml = "0.20.0" +worldgen = "0.5.3" [dependencies.s2dc] git = "https://github.com/crumblingstatue/s2dc.git" diff --git a/src/app.rs b/src/app.rs index 1b17378..7602a72 100644 --- a/src/app.rs +++ b/src/app.rs @@ -100,7 +100,7 @@ impl App { .clamp(-terminal_velocity, terminal_velocity); let mut on_screen_tile_ents = Vec::new(); for_each_tile_on_screen(self.game.camera_offset, |tp, _sp| { - let tid = self.game.world.tile_at_mut(tp).mid; + let tid = self.game.world.tile_at_mut(tp, &self.game.worldgen).mid; if tid == Tile::EMPTY { return; } @@ -163,11 +163,11 @@ impl App { self.game.player.col_en.en.pos.y = wpos.y as i32; } if self.input.lmb_down { - let t = self.game.world.tile_at_mut(mouse_tpos); + let t = self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen); t.mid = 0; t.fg = 0; } else if self.input.rmb_down { - let t = self.game.world.tile_at_mut(mouse_tpos); + let t = self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen); if self.game.tile_to_place != 7 { t.mid = self.game.tile_to_place; } else { diff --git a/src/game.rs b/src/game.rs index 3c9085a..f11ec22 100644 --- a/src/game.rs +++ b/src/game.rs @@ -9,6 +9,7 @@ use crate::{ math::{wp_to_tp, WorldPos}, res::Res, world::{Tile, TileId, TilePos, World}, + worldgen::Worldgen, }; use self::player::Player; @@ -21,6 +22,7 @@ pub struct GameState { pub tile_to_place: TileId, pub current_biome: Biome, pub prev_biome: Biome, + pub worldgen: Worldgen, } #[derive(PartialEq, Eq, Clone, Copy)] @@ -33,7 +35,7 @@ impl GameState { pub(crate) fn draw_world(&mut self, rw: &mut RenderWindow, res: &Res) { let mut s = Sprite::with_texture(&res.tile_atlas); for_each_tile_on_screen(self.camera_offset, |tp, sp| { - let tile = self.world.tile_at_mut(tp); + let tile = self.world.tile_at_mut(tp, &self.worldgen); s.set_position(sp.to_sf_vec()); if tile.bg != Tile::EMPTY { s.set_texture_rect(Rect::new((tile.bg - 1) as i32 * 32, 0, 32, 32)); @@ -97,6 +99,7 @@ impl Default for GameState { tile_to_place: 1, current_biome: Biome::Surface, prev_biome: Biome::Surface, + worldgen: Worldgen::default(), } } } diff --git a/src/main.rs b/src/main.rs index e005061..da54089 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ mod input; mod math; mod res; mod world; +mod worldgen; use app::App; diff --git a/src/world.rs b/src/world.rs index 8254bbd..17c0f2f 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,12 +1,13 @@ use fnv::FnvHashMap; -use rand::{thread_rng, Rng}; + +use crate::worldgen::Worldgen; pub type ChunkPosScalar = u16; #[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)] pub struct ChunkPos { - x: ChunkPosScalar, - y: ChunkPosScalar, + pub x: ChunkPosScalar, + pub y: ChunkPosScalar, } #[derive(Default)] @@ -19,9 +20,12 @@ impl World { /// Get mutable access to the tile at `pos`. /// /// Loads or generates the containing chunk if necessary. - pub fn tile_at_mut(&mut self, pos: TilePos) -> &mut Tile { + pub fn tile_at_mut(&mut self, pos: TilePos, worldgen: &Worldgen) -> &mut Tile { let (chk, local) = pos.to_chunk_and_local(); - let chk = self.chunks.entry(chk).or_insert_with(|| Chunk::gen(chk)); + let chk = self + .chunks + .entry(chk) + .or_insert_with(|| Chunk::gen(chk, worldgen)); chk.at_mut(local) } } @@ -100,29 +104,19 @@ pub struct Chunk { } impl Chunk { - pub fn gen(pos: ChunkPos) -> Self { - let mut rng = thread_rng(); + pub fn gen(pos: ChunkPos, worldgen: &Worldgen) -> Self { let mut tiles = [Tile { bg: 0, mid: 0, fg: 0, }; CHUNK_N_TILES]; - if pos.y == 156 { - for (i, b) in tiles.iter_mut().enumerate() { - if i / CHUNK_EXTENT as usize == 0 { - b.fg = 8; - } - b.mid = 2; - b.bg = 9; - } - } - if pos.y > 156 { - for b in &mut tiles { - b.bg = 7; - b.mid = 1; - if rng.gen_bool(0.1) { - b.fg = 6; - } + let noise = worldgen.chunk_noise(pos); + if pos.y >= 156 { + for (i, t) in tiles.iter_mut().enumerate() { + let x = i % CHUNK_EXTENT as usize; + let y = i / CHUNK_EXTENT as usize; + let noise = noise[x][y]; + *t = noise; } } // Unbreakable layer at bottom diff --git a/src/worldgen.rs b/src/worldgen.rs new file mode 100644 index 0000000..476cdcd --- /dev/null +++ b/src/worldgen.rs @@ -0,0 +1,76 @@ +use rand::{thread_rng, Rng}; +use worldgen::{ + constraint, + noise::perlin::PerlinNoise, + noisemap::{NoiseMap, NoiseMapGenerator, Seed, Step}, + world::{ + tile::{Constraint, ConstraintType}, + Size, Tile, World, + }, +}; + +use crate::world::{ChunkPos, Tile as Tl, CHUNK_EXTENT}; + +pub struct Worldgen { + world: World, +} + +impl Default for Worldgen { + fn default() -> Self { + let noise = PerlinNoise::new(); + let mut rng = thread_rng(); + + let nm1 = NoiseMap::new(noise) + .set(Seed::of(rng.gen::())) + .set(Step::of(0.005, 0.005)); + + let nm2 = NoiseMap::new(noise) + .set(Seed::of(rng.gen::())) + .set(Step::of(0.05, 0.05)); + + let nm = Box::new(nm1 + nm2 * 3); + + let world = World::new() + .set(Size::of(CHUNK_EXTENT as i64, CHUNK_EXTENT as i64)) + // Dirt coal + .add( + Tile::new(Tl { + bg: 9, + mid: 2, + fg: 6, + }) + .when(constraint!(nm.clone(), < -0.8)), + ) + // Dirt + .add( + Tile::new(Tl { + bg: 9, + mid: 2, + fg: 0, + }) + .when(constraint!(nm.clone(), < -0.1)), + ) + // Stone + .add( + Tile::new(Tl { + bg: 7, + mid: 1, + fg: 0, + }) + .when(constraint!(nm.clone(), < 0.45)), + ) + // Dirt wall + .add(Tile::new(Tl { + bg: 9, + mid: 0, + fg: 0, + })); + Self { world } + } +} + +impl Worldgen { + pub fn chunk_noise(&self, pos: ChunkPos) -> Vec> { + self.world.generate(pos.x as i64, pos.y as i64).unwrap() + } +}