Refactor
[kaka/rust-sdl-test.git] / src / core / level.rs
CommitLineData
a6b57e45
TW
1use common::Point2D;
2use core::render::Renderer;
3use rand::Rng;
4use sprites::SpriteManager;
5
6////////// LEVEL ///////////////////////////////////////////////////////////////
7
8#[derive(Default)]
9pub struct Level {
10 pub gravity: Point2D<f64>,
11 pub ground: f64, // just to have something
12 pub grid: Grid,
13 iterations: u8,
14}
15
16impl Level {
17 pub fn new(gravity: Point2D<f64>, ground: f64) -> Self {
18 Level { gravity, ground, grid: Grid::generate(10), iterations: 10 }
19 }
20
21 pub fn regenerate(&mut self) {
22 self.grid = Grid::generate(self.iterations);
23 }
24
25 pub fn increase_iteration(&mut self) {
26 self.iterations += 1;
27 self.regenerate();
28 println!("iterate {} time(s)", self.iterations);
29 }
30
31 pub fn decrease_iteration(&mut self) {
32 self.iterations -= 1;
33 self.regenerate();
34 println!("iterate {} time(s)", self.iterations);
35 }
36
37 pub fn render(&mut self, renderer: &mut Renderer, _sprites: &SpriteManager) {
38 let w = renderer.viewport().0 as i32;
39
40 renderer.canvas().set_draw_color((64, 64, 64));
41 let size = self.grid.cell_size;
42 for x in 0..self.grid.width {
43 for y in 0..self.grid.height {
44 if self.grid.cells[x][y] {
45 renderer.canvas().fill_rect(sdl2::rect::Rect::new(x as i32 * size as i32, y as i32 * size as i32, size as u32, size as u32)).unwrap();
46 }
47 }
48 }
49
50 for i in 1..11 {
51 let y = (i * i - 1) as i32 + self.ground as i32;
52 renderer.canvas().set_draw_color((255 - i * 20, 255 - i * 20, 0));
53 renderer.canvas().draw_line((0, y), (w, y)).unwrap();
54 }
55 }
56}
57
58////////// GRID ////////////////////////////////////////////////////////////////
59
60#[derive(Default)]
61pub struct Grid {
62 pub width: usize,
63 pub height: usize,
64 pub cell_size: usize,
65 pub cells: Vec<Vec<bool>>,
66}
67
68impl Grid {
69 fn generate(iterations: u8) -> Grid {
60276654
TW
70 let cell_size = 20;
71 let (width, height) = (2560 / cell_size, 1440 / cell_size);
72
73 let mut grid = Grid {
74 cell_size,
75 width,
76 height,
77 cells: vec!(vec!(true; height); width),
78 };
79
80 // start with some noise
81// grid.simplex_noise();
82 grid.random_noise();
a6b57e45 83
60276654
TW
84 // smooth with cellular automata
85 grid.smooth(iterations);
86// grid.smooth_until_equilibrium();
87
88 // increase resolution
89 for _i in 0..1 {
90 grid = grid.subdivide();
91 grid.smooth(iterations);
92 }
93
94 grid
95 }
96
97 #[allow(dead_code)]
98 fn simplex_noise(&mut self) {
99 use noise::{NoiseFn, OpenSimplex, Seedable};
100 let noise = OpenSimplex::new().set_seed(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32);
101 self.set_each(|x, y| noise.get([x as f64 / 12.0, y as f64 / 12.0]) > 0.055, 1);
102 }
103
104 #[allow(dead_code)]
105 fn random_noise(&mut self) {
a6b57e45 106 let mut rng = rand::thread_rng();
60276654
TW
107 self.set_each(|_x, _y| rng.gen_range(0, 100) > 55, 1);
108 }
a6b57e45 109
60276654
TW
110 #[allow(dead_code)]
111 fn smooth(&mut self, iterations: u8) {
112 let distance = 1;
113 for _i in 0..iterations {
114 let mut next = vec!(vec!(true; self.height); self.width);
115 for x in distance..(self.width - distance) {
116 for y in distance..(self.height - distance) {
117 match Grid::neighbours(&self.cells, x, y, distance) {
118 n if n < 4 => next[x][y] = false,
119 n if n > 4 => next[x][y] = true,
120 _ => next[x][y] = self.cells[x][y]
121 }
122 }
123 }
124 if self.cells == next {
125 break; // exit early
126 } else {
127 self.cells = next;
a6b57e45
TW
128 }
129 }
60276654 130 }
a6b57e45 131
60276654
TW
132 #[allow(dead_code)]
133 fn smooth_until_equilibrium(&mut self) {
134 let distance = 1;
135 let mut count = 0;
136 loop {
137 count += 1;
138 let mut next = vec!(vec!(true; self.height); self.width);
139 for x in distance..(self.width - distance) {
140 for y in distance..(self.height - distance) {
141 match Grid::neighbours(&self.cells, x, y, distance) {
a6b57e45
TW
142 n if n < 4 => next[x][y] = false,
143 n if n > 4 => next[x][y] = true,
60276654 144 _ => next[x][y] = self.cells[x][y]
a6b57e45
TW
145 };
146 }
147 }
60276654 148 if self.cells == next {
a6b57e45
TW
149 break;
150 } else {
60276654 151 self.cells = next;
a6b57e45
TW
152 }
153 }
60276654 154 println!("{} iterations needed", count);
a6b57e45
TW
155 }
156
60276654 157 fn neighbours(grid: &Vec<Vec<bool>>, px: usize, py: usize, distance: usize) -> u8 {
a6b57e45 158 let mut count = 0;
60276654
TW
159 for x in (px - distance)..=(px + distance) {
160 for y in (py - distance)..=(py + distance) {
a6b57e45
TW
161 if !(x == px && y == py) && grid[x][y] {
162 count += 1;
163 }
164 }
165 }
166 count
167 }
60276654
TW
168
169 fn set_each<F: FnMut(usize, usize) -> bool>(&mut self, mut func: F, walls: usize) {
170 for x in walls..(self.width - walls) {
171 for y in walls..(self.height - walls) {
172 self.cells[x][y] = func(x, y);
173 }
174 }
175 }
176
177 fn subdivide(&mut self) -> Grid {
178 let (width, height) = (self.width * 2, self.height * 2);
179 let mut cells = vec!(vec!(true; height); width);
180 for x in 1..(width - 1) {
181 for y in 1..(height - 1) {
182 cells[x][y] = self.cells[x / 2][y / 2];
183 }
184 }
185 Grid {
186 cell_size: self.cell_size / 2,
187 width,
188 height,
189 cells
190 }
191 }
a6b57e45 192}