X-Git-Url: http://www.dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fcore%2Flevel.rs;h=bab89e0caf54306821a754148522ffadc2704503;hb=602766547385196282a03bb13cfdb785f6446a7a;hp=f0c6c0e1ee248daad083fb6f2a55da49555d25fd;hpb=a6b57e450092f390103915bb8b936ceb9a116b03;p=kaka%2Frust-sdl-test.git diff --git a/src/core/level.rs b/src/core/level.rs index f0c6c0e..bab89e0 100644 --- a/src/core/level.rs +++ b/src/core/level.rs @@ -67,54 +67,97 @@ pub struct Grid { impl Grid { fn generate(iterations: u8) -> Grid { - let cell_size = 10; - let (width, height) = (1280 / cell_size, 600 / cell_size); - let mut cells = vec!(vec!(true; height); width); + let cell_size = 20; + let (width, height) = (2560 / cell_size, 1440 / cell_size); + + let mut grid = Grid { + cell_size, + width, + height, + cells: vec!(vec!(true; height); width), + }; + + // start with some noise +// grid.simplex_noise(); + grid.random_noise(); + // smooth with cellular automata + grid.smooth(iterations); +// grid.smooth_until_equilibrium(); + + // increase resolution + for _i in 0..1 { + grid = grid.subdivide(); + grid.smooth(iterations); + } + + grid + } + + #[allow(dead_code)] + fn simplex_noise(&mut self) { + use noise::{NoiseFn, OpenSimplex, Seedable}; + let noise = OpenSimplex::new().set_seed(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32); + self.set_each(|x, y| noise.get([x as f64 / 12.0, y as f64 / 12.0]) > 0.055, 1); + } + + #[allow(dead_code)] + fn random_noise(&mut self) { let mut rng = rand::thread_rng(); + self.set_each(|_x, _y| rng.gen_range(0, 100) > 55, 1); + } - // randomize - for x in 1..(width - 1) { - for y in 1..(height - 1) { - cells[x][y] = rng.gen_range(0, 100) > 55; + #[allow(dead_code)] + fn smooth(&mut self, iterations: u8) { + let distance = 1; + for _i in 0..iterations { + let mut next = vec!(vec!(true; self.height); self.width); + for x in distance..(self.width - distance) { + for y in distance..(self.height - distance) { + match Grid::neighbours(&self.cells, x, y, distance) { + n if n < 4 => next[x][y] = false, + n if n > 4 => next[x][y] = true, + _ => next[x][y] = self.cells[x][y] + } + } + } + if self.cells == next { + break; // exit early + } else { + self.cells = next; } } + } - // smooth - // let mut count = 0; - // loop { - // count += 1; - // println!("iteration {}", count); - for _i in 0..iterations { - let mut next = vec!(vec!(true; height); width); - for x in 1..(width - 1) { - for y in 1..(height - 1) { - match Grid::neighbours(&cells, x, y) { + #[allow(dead_code)] + fn smooth_until_equilibrium(&mut self) { + let distance = 1; + let mut count = 0; + loop { + count += 1; + let mut next = vec!(vec!(true; self.height); self.width); + for x in distance..(self.width - distance) { + for y in distance..(self.height - distance) { + match Grid::neighbours(&self.cells, x, y, distance) { n if n < 4 => next[x][y] = false, n if n > 4 => next[x][y] = true, - _ => next[x][y] = cells[x][y] + _ => next[x][y] = self.cells[x][y] }; } } - if cells == next { + if self.cells == next { break; } else { - cells = next; + self.cells = next; } } - - Grid { - width, - height, - cell_size, - cells - } + println!("{} iterations needed", count); } - fn neighbours(grid: &Vec>, px: usize, py: usize) -> u8 { + fn neighbours(grid: &Vec>, px: usize, py: usize, distance: usize) -> u8 { let mut count = 0; - for x in (px - 1)..=(px + 1) { - for y in (py - 1)..=(py + 1) { + for x in (px - distance)..=(px + distance) { + for y in (py - distance)..=(py + distance) { if !(x == px && y == py) && grid[x][y] { count += 1; } @@ -122,4 +165,28 @@ impl Grid { } count } + + fn set_each bool>(&mut self, mut func: F, walls: usize) { + for x in walls..(self.width - walls) { + for y in walls..(self.height - walls) { + self.cells[x][y] = func(x, y); + } + } + } + + fn subdivide(&mut self) -> Grid { + let (width, height) = (self.width * 2, self.height * 2); + let mut cells = vec!(vec!(true; height); width); + for x in 1..(width - 1) { + for y in 1..(height - 1) { + cells[x][y] = self.cells[x / 2][y / 2]; + } + } + Grid { + cell_size: self.cell_size / 2, + width, + height, + cells + } + } }