Commit | Line | Data |
---|---|---|
1f42d724 | 1 | use common::{Point, Dimension}; |
79914631 TW |
2 | use core::render::Renderer; |
3 | use sprites::SpriteManager; | |
1f42d724 TW |
4 | use std::rc::Rc; |
5 | use {point, dimen}; | |
79914631 TW |
6 | |
7 | mod lvlgen; | |
8 | ||
9 | pub use self::lvlgen::LevelGenerator; | |
10 | ||
11 | ////////// LEVEL /////////////////////////////////////////////////////////////// | |
12 | ||
13 | #[derive(Default)] | |
14 | pub struct Level { | |
e570927a | 15 | pub gravity: Point<f64>, |
37f3e1ed | 16 | pub grid: Grid<bool>, |
1f42d724 TW |
17 | walls: Vec<Rc<WallRegion>>, |
18 | wall_grid: Grid<Vec<Rc<WallEdge>>>, | |
79914631 TW |
19 | } |
20 | ||
21 | impl Level { | |
1f42d724 TW |
22 | pub fn new(gravity: Point<f64>, grid: Grid<bool>, mut walls: Vec<Rc<WallRegion>>) -> Self { |
23 | let size = (2560, 1440); // TODO: get actual size from walls or something | |
24 | let wall_grid = Level::build_wall_grid(&mut walls, &size.into()); | |
25 | dbg!(&wall_grid.cell_size); | |
26 | Level { | |
27 | gravity, | |
28 | grid, | |
29 | walls, | |
30 | wall_grid, | |
31 | } | |
32 | } | |
33 | ||
34 | /// Creates a grid of wall edges for fast lookup | |
35 | fn build_wall_grid(walls: &mut Vec<Rc<WallRegion>>, lvlsize: &Dimension<usize>) -> Grid<Vec<Rc<WallEdge>>> { | |
36 | let size = dimen!(lvlsize.width / 20, lvlsize.height / 20); // TODO: make sure all walls fit within the grid bounds | |
37 | let cs = point!(lvlsize.width / size.width, lvlsize.height / size.height); | |
38 | //let cs = point!(cell_size.width as f64, cell_size.height as f64); | |
39 | let mut grid = vec!(vec!(vec!(); size.height); size.width); | |
40 | ||
41 | for wall in walls { | |
42 | for edge in &wall.edges { | |
43 | // TODO: include cells that this edge overlaps | |
44 | for p in &[edge.p1, edge.p2] { | |
45 | let p = point!(p.x as usize, p.y as usize) / cs; | |
46 | grid[0.max(p.x as usize).min(size.width - 1)][0.max(p.y as usize).min(size.height - 1)].push(Rc::clone(edge)); | |
47 | } | |
48 | } | |
49 | } | |
50 | ||
51 | Grid { | |
52 | size, | |
53 | cell_size: dimen!(cs.x, cs.y), | |
54 | cells: grid, | |
55 | } | |
56 | } | |
79914631 TW |
57 | |
58 | pub fn render(&mut self, renderer: &mut Renderer, _sprites: &SpriteManager) { | |
1f42d724 | 59 | // original grid |
79914631 | 60 | renderer.canvas().set_draw_color((64, 64, 64)); |
1f42d724 TW |
61 | let size = &self.grid.cell_size; |
62 | for x in 0..self.grid.size.width { | |
63 | for y in 0..self.grid.size.height { | |
79914631 | 64 | if self.grid.cells[x][y] { |
1f42d724 TW |
65 | renderer.canvas().fill_rect(sdl2::rect::Rect::new( |
66 | x as i32 * size.width as i32, | |
67 | y as i32 * size.height as i32, | |
68 | size.width as u32, | |
69 | size.height as u32)).unwrap(); | |
70 | } | |
71 | } | |
72 | } | |
73 | ||
74 | // wall grid | |
75 | renderer.canvas().set_draw_color((0, 32, 0)); | |
76 | let size = &self.wall_grid.cell_size; | |
77 | for x in 0..self.wall_grid.size.width { | |
78 | for y in 0..self.wall_grid.size.height { | |
79 | if !self.wall_grid.cells[x][y].is_empty() { | |
80 | renderer.canvas().fill_rect(sdl2::rect::Rect::new( | |
81 | x as i32 * size.width as i32, | |
82 | y as i32 * size.height as i32, | |
83 | size.width as u32, | |
84 | size.height as u32)).unwrap(); | |
79914631 TW |
85 | } |
86 | } | |
87 | } | |
88 | ||
1f42d724 | 89 | // walls |
79914631 | 90 | for wall in &self.walls { |
1f42d724 TW |
91 | for e in &wall.edges { |
92 | renderer.draw_line( | |
93 | <(i32, i32)>::from(e.p1.to_i32()), | |
94 | <(i32, i32)>::from(e.p2.to_i32()), | |
95 | (255, 255, 0)); | |
79914631 | 96 | } |
79914631 TW |
97 | } |
98 | } | |
99 | } | |
100 | ||
101 | ////////// GRID //////////////////////////////////////////////////////////////// | |
102 | ||
1f42d724 | 103 | #[derive(Debug, Default)] |
37f3e1ed | 104 | pub struct Grid<T> { |
1f42d724 TW |
105 | pub size: Dimension<usize>, |
106 | pub cell_size: Dimension<usize>, | |
37f3e1ed | 107 | pub cells: Vec<Vec<T>>, |
79914631 | 108 | } |
1f42d724 TW |
109 | |
110 | ////////// WALL REGION ///////////////////////////////////////////////////////// | |
111 | ||
112 | #[derive(Debug)] | |
113 | pub struct WallRegion { | |
114 | edges: Vec<Rc<WallEdge>>, | |
115 | } | |
116 | ||
117 | impl WallRegion { | |
118 | pub fn new(points: Vec<Point<f64>>) -> Rc<Self> { | |
119 | let mut edges = vec!(); | |
120 | ||
121 | for i in 0..points.len() { | |
122 | let edge = Rc::new(WallEdge { | |
123 | index: i, | |
124 | p1: points[i], | |
125 | p2: points[(i + 1) % points.len()], | |
126 | }); | |
127 | edges.push(edge); | |
128 | } | |
129 | ||
130 | Rc::new(WallRegion { edges }) | |
131 | } | |
132 | ||
133 | #[allow(dead_code)] | |
134 | fn next(&self, index: usize) -> Rc<WallEdge> { | |
135 | let index = (index + 1) % self.edges.len(); | |
136 | Rc::clone(&self.edges[index]) | |
137 | } | |
138 | ||
139 | #[allow(dead_code)] | |
140 | fn previous(&self, index: usize) -> Rc<WallEdge> { | |
141 | let index = (index + self.edges.len() + 1) % self.edges.len(); | |
142 | Rc::clone(&self.edges[index]) | |
143 | } | |
144 | } | |
145 | ||
146 | ////////// WALL EDGE /////////////////////////////////////////////////////////// | |
147 | ||
148 | #[derive(Debug, Default)] | |
149 | struct WallEdge { | |
150 | index: usize, | |
151 | pub p1: Point<f64>, | |
152 | pub p2: Point<f64>, | |
153 | } |