Generate a grid with cellular automata
[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 {
70 let cell_size = 10;
71 let (width, height) = (1280 / cell_size, 600 / cell_size);
72 let mut cells = vec!(vec!(true; height); width);
73
74 let mut rng = rand::thread_rng();
75
76 // randomize
77 for x in 1..(width - 1) {
78 for y in 1..(height - 1) {
79 cells[x][y] = rng.gen_range(0, 100) > 55;
80 }
81 }
82
83 // smooth
84 // let mut count = 0;
85 // loop {
86 // count += 1;
87 // println!("iteration {}", count);
88 for _i in 0..iterations {
89 let mut next = vec!(vec!(true; height); width);
90 for x in 1..(width - 1) {
91 for y in 1..(height - 1) {
92 match Grid::neighbours(&cells, x, y) {
93 n if n < 4 => next[x][y] = false,
94 n if n > 4 => next[x][y] = true,
95 _ => next[x][y] = cells[x][y]
96 };
97 }
98 }
99 if cells == next {
100 break;
101 } else {
102 cells = next;
103 }
104 }
105
106 Grid {
107 width,
108 height,
109 cell_size,
110 cells
111 }
112 }
113
114 fn neighbours(grid: &Vec<Vec<bool>>, px: usize, py: usize) -> u8 {
115 let mut count = 0;
116 for x in (px - 1)..=(px + 1) {
117 for y in (py - 1)..=(py + 1) {
118 if !(x == px && y == py) && grid[x][y] {
119 count += 1;
120 }
121 }
122 }
123 count
124 }
125}