Cleaning
This commit is contained in:
		
							parent
							
								
									7bab06b2b6
								
							
						
					
					
						commit
						a66e596db0
					
				| @ -43,8 +43,8 @@ fn main() { | ||||
|                         let x = ((x - left_panel_size.x as i32) / SPRITE_SIZE_I32) as usize; | ||||
|                         let y = ((y - top_panel_size.y as i32) / SPRITE_SIZE_I32) as usize; | ||||
| 
 | ||||
|                         if let Some(tile) = map.tile(y, x) { | ||||
|                             if tile == CollisionTile::empty() { | ||||
|                         if let Some(tile) = map.collision_tile(y, x) { | ||||
|                             if tile.is_empty() { | ||||
|                                 map.set_tile(y, x, CollisionTile::full()); | ||||
|                             } else { | ||||
|                                 map.set_tile(y, x, CollisionTile::empty()); | ||||
|  | ||||
| @ -82,6 +82,16 @@ impl CollisionTile { | ||||
|             from_bottom: true, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Tests whether a collision tile is full or not.
 | ||||
|     pub fn is_full(self) -> bool { | ||||
|         self.from_top && self.from_left && self.from_right && self.from_bottom | ||||
|     } | ||||
| 
 | ||||
|     /// Tests whether a collision tile is empty or not.
 | ||||
|     pub fn is_empty(self) -> bool { | ||||
|         !self.from_top && !self.from_left && !self.from_right && !self.from_bottom | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// This struct represents a renderable tile linking to its part in the tileset texture.
 | ||||
| @ -94,79 +104,53 @@ impl GraphicTile { | ||||
|     /// Creates the correct graphic tile depending on the neighbours.
 | ||||
|     ///
 | ||||
|     /// A none will be considered solid.
 | ||||
|     pub fn from_neighbour_options( | ||||
|         top_left: Option<CollisionTile>, | ||||
|         top: Option<CollisionTile>, | ||||
|         top_right: Option<CollisionTile>, | ||||
|         right: Option<CollisionTile>, | ||||
|         bottom_right: Option<CollisionTile>, | ||||
|         bottom: Option<CollisionTile>, | ||||
|         bottom_left: Option<CollisionTile>, | ||||
|         left: Option<CollisionTile>, | ||||
|     ) -> GraphicTile { | ||||
|         GraphicTile::from_neighbours( | ||||
|             top_left.unwrap_or_else(CollisionTile::full), | ||||
|             top.unwrap_or_else(CollisionTile::full), | ||||
|             top_right.unwrap_or_else(CollisionTile::full), | ||||
|             right.unwrap_or_else(CollisionTile::full), | ||||
|             bottom_right.unwrap_or_else(CollisionTile::full), | ||||
|             bottom.unwrap_or_else(CollisionTile::full), | ||||
|             bottom_left.unwrap_or_else(CollisionTile::full), | ||||
|             left.unwrap_or_else(CollisionTile::full), | ||||
|         ) | ||||
|     pub fn from_neighbour_options(tiles: &[Option<CollisionTile>; 8]) -> GraphicTile { | ||||
|         GraphicTile::from_neighbours(&[ | ||||
|             tiles[0].unwrap_or_else(CollisionTile::full), | ||||
|             tiles[1].unwrap_or_else(CollisionTile::full), | ||||
|             tiles[2].unwrap_or_else(CollisionTile::full), | ||||
|             tiles[3].unwrap_or_else(CollisionTile::full), | ||||
|             tiles[4].unwrap_or_else(CollisionTile::full), | ||||
|             tiles[5].unwrap_or_else(CollisionTile::full), | ||||
|             tiles[6].unwrap_or_else(CollisionTile::full), | ||||
|             tiles[7].unwrap_or_else(CollisionTile::full), | ||||
|         ]) | ||||
|     } | ||||
| 
 | ||||
|     /// Creates the correct graphic tile depending on the neighbours.
 | ||||
|     pub fn from_neighbours( | ||||
|         top_left: CollisionTile, | ||||
|         top: CollisionTile, | ||||
|         top_right: CollisionTile, | ||||
|         right: CollisionTile, | ||||
|         bottom_right: CollisionTile, | ||||
|         bottom: CollisionTile, | ||||
|         bottom_left: CollisionTile, | ||||
|         left: CollisionTile, | ||||
|     ) -> GraphicTile { | ||||
|     pub fn from_neighbours(tiles: &[CollisionTile; 8]) -> GraphicTile { | ||||
| 
 | ||||
|         let mut byte = 0; | ||||
| 
 | ||||
|         if top_left != CollisionTile::full() || | ||||
|            left     != CollisionTile::full() || | ||||
|            top      != CollisionTile::full() { | ||||
|         if !tiles[7].is_full() || !tiles[0].is_full() || !tiles[1].is_full() { | ||||
|             byte += 1; | ||||
|         } | ||||
| 
 | ||||
|         if top != CollisionTile::full() { | ||||
|         if !tiles[1].is_full() { | ||||
|             byte += 2; | ||||
|         } | ||||
| 
 | ||||
|         if top_right != CollisionTile::full() || | ||||
|            top       != CollisionTile::full() || | ||||
|            right     != CollisionTile::full() { | ||||
|         if !tiles[1] .is_full() || !tiles[2].is_full() || !tiles[3].is_full() { | ||||
|             byte += 4; | ||||
|         } | ||||
| 
 | ||||
|         if right != CollisionTile::full() { | ||||
|         if !tiles[3] .is_full() { | ||||
|             byte += 8; | ||||
|         } | ||||
| 
 | ||||
|         if bottom_right != CollisionTile::full() || | ||||
|            bottom       != CollisionTile::full() || | ||||
|            right        != CollisionTile::full() { | ||||
|         if !tiles[3].is_full() || !tiles[4].is_full() || !tiles[5].is_full() { | ||||
|             byte += 16; | ||||
|         } | ||||
| 
 | ||||
|         if bottom != CollisionTile::full() { | ||||
|         if !tiles[5].is_full() { | ||||
|             byte += 32; | ||||
|         } | ||||
| 
 | ||||
|         if bottom_left != CollisionTile::full() || | ||||
|            bottom      != CollisionTile::full() || | ||||
|            left        != CollisionTile::full() { | ||||
|         if !tiles[5].is_full() || !tiles[6].is_full() || !tiles[7].is_full() { | ||||
|             byte += 64; | ||||
|         } | ||||
| 
 | ||||
|         if left != CollisionTile::full() { | ||||
|         if !tiles[7] .is_full() { | ||||
|             byte += 128; | ||||
|         } | ||||
| 
 | ||||
| @ -214,14 +198,34 @@ impl Drawable for PositionedTile { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// The map represents the tiles contained in a level.
 | ||||
| /// The content of a map that needs to be saved.
 | ||||
| #[derive(Serialize, Deserialize)] | ||||
| struct SaveMap { | ||||
|     /// The entrance point of the character in the map.
 | ||||
|     entrance: (usize, usize), | ||||
| 
 | ||||
|     /// The collision tiles contained in the level.
 | ||||
|     collision_tiles: Matrix<CollisionTile>, | ||||
| } | ||||
| 
 | ||||
| impl SaveMap { | ||||
|     /// Creates a map from the save map.
 | ||||
|     fn to_map(self) -> Map { | ||||
|         Map::from_entrance_and_collision_tiles(self.entrance, self.collision_tiles) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// The map represents the tiles contained in a level.
 | ||||
| #[derive(Clone)] | ||||
| pub struct Map { | ||||
|     /// The entrace point of the character in the map.
 | ||||
|     entrance: (usize, usize), | ||||
| 
 | ||||
|     /// The tiles contained in the level.
 | ||||
|     tiles: Matrix<(CollisionTile, GraphicTile)>, | ||||
|     /// The collision tiles contained in the level.
 | ||||
|     collision_tiles: Matrix<CollisionTile>, | ||||
| 
 | ||||
|     /// The graphic tiles contained in the level.
 | ||||
|     graphic_tiles: Matrix<GraphicTile>, | ||||
| } | ||||
| 
 | ||||
| impl Map { | ||||
| @ -237,21 +241,29 @@ impl Map { | ||||
|         Map::from_collision_tiles(tiles) | ||||
|     } | ||||
| 
 | ||||
|     /// Creates a SaveMap from a map
 | ||||
|     fn save_map(&self) -> SaveMap { | ||||
|         SaveMap { | ||||
|             entrance: self.entrance, | ||||
|             collision_tiles: self.collision_tiles.clone(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Encodes the map into a binary format.
 | ||||
|     pub fn encode(&self) -> Result<Vec<u8>> { | ||||
|         serialize(&self).map_err(Error::Encoding) | ||||
|         serialize(&self.save_map()).map_err(Error::Encoding) | ||||
|     } | ||||
| 
 | ||||
|     /// Decodes a map from bytes.
 | ||||
|     pub fn decode(content: &[u8]) -> Result<Map> { | ||||
|         deserialize(content).map_err(Error::Decoding) | ||||
|         deserialize(content).map(SaveMap::to_map).map_err(Error::Decoding) | ||||
|     } | ||||
| 
 | ||||
|     /// Saves the map to a file.
 | ||||
|     pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<()> { | ||||
|         let file = File::create(path.as_ref()).map_err(Error::Save)?; | ||||
|         let mut writer = BufWriter::new(file); | ||||
|         serialize_into(&mut writer, &self).map_err(Error::Encoding)?; | ||||
|         serialize_into(&mut writer, &self.save_map()).map_err(Error::Encoding)?; | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
| @ -259,85 +271,83 @@ impl Map { | ||||
|     pub fn load<P: AsRef<Path>>(path: P) -> Result<Map> { | ||||
|         let file = File::open(path.as_ref()).map_err(Error::Load)?; | ||||
|         let mut reader = BufReader::new(file); | ||||
|         Ok(deserialize_from(&mut reader).map_err(Error::Decoding)?) | ||||
|         Ok(deserialize_from(&mut reader).map(SaveMap::to_map).map_err(Error::Decoding)?) | ||||
|     } | ||||
| 
 | ||||
|     /// Creates a map from its tiles.
 | ||||
|     pub fn from_collision_tiles(tiles: Matrix<CollisionTile>) -> Map { | ||||
|         let rows = tiles.rows(); | ||||
|         let cols = tiles.cols(); | ||||
|     /// Creates a map from its entrance and collision tiles.
 | ||||
|     pub fn from_entrance_and_collision_tiles(e: (usize, usize), t: Matrix<CollisionTile>) -> Map { | ||||
|         let rows = t.rows(); | ||||
|         let cols = t.cols(); | ||||
| 
 | ||||
|         let mut matrix = | ||||
|             Matrix::from_size(rows, cols, (CollisionTile::empty(), GraphicTile(None))); | ||||
|         let graphic_tiles = Matrix::from_size(rows, cols, GraphicTile(None)); | ||||
| 
 | ||||
|         for i in 0..rows { | ||||
|             for j in 0..cols { | ||||
|                 let graphic = if tiles[(i, j)] == CollisionTile::full() { | ||||
|                     // TODO This is uggly
 | ||||
|                     // If there is an overflow, we should give None instead
 | ||||
|                     let (i, j) = (i as isize, j as isize); | ||||
|         let mut map = Map { | ||||
|             entrance: e, | ||||
|             collision_tiles: t, | ||||
|             graphic_tiles, | ||||
|         }; | ||||
| 
 | ||||
|                     GraphicTile::from_neighbour_options( | ||||
|                         tiles.get(((i - 1) as usize, (j - 1) as usize)).cloned(), | ||||
|                         tiles.get(((i    ) as usize, (j - 1) as usize)).cloned(), | ||||
|                         tiles.get(((i + 1) as usize, (j - 1) as usize)).cloned(), | ||||
|                         tiles.get(((i + 1) as usize, (j    ) as usize)).cloned(), | ||||
|                         tiles.get(((i + 1) as usize, (j + 1) as usize)).cloned(), | ||||
|                         tiles.get(((i    ) as usize, (j + 1) as usize)).cloned(), | ||||
|                         tiles.get(((i - 1) as usize, (j + 1) as usize)).cloned(), | ||||
|                         tiles.get(((i - 1) as usize, (j    ) as usize)).cloned(), | ||||
|                     ) | ||||
|                 } else { | ||||
|                     GraphicTile(None) | ||||
|                 }; | ||||
| 
 | ||||
|                 matrix[(i, j)] = (tiles[(i, j)], graphic); | ||||
|         for i in 0 .. rows { | ||||
|             for j in 0 .. cols { | ||||
|                 map.graphic_tiles[(i, j)] = map.graphic_tile(i, j); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Map { | ||||
|             entrance: Map::find_entrance(&matrix), | ||||
|             tiles: matrix, | ||||
|         } | ||||
|         map | ||||
|     } | ||||
| 
 | ||||
|     /// Creates a map from its tiles.
 | ||||
|     pub fn from_collision_tiles(collision_tiles: Matrix<CollisionTile>) -> Map { | ||||
|         let entrance = Map::find_entrance(&collision_tiles); | ||||
|         Map::from_entrance_and_collision_tiles(entrance, collision_tiles) | ||||
|     } | ||||
| 
 | ||||
|     /// Creates the neighbours of a tile.
 | ||||
|     pub fn neighbours(&self, i: isize, j: isize) -> [Option<CollisionTile>; 8] { | ||||
|         [ | ||||
|             self.collision_tiles.get_isize(i - 1, j - 1).cloned(), | ||||
|             self.collision_tiles.get_isize(i - 1, j    ).cloned(), | ||||
|             self.collision_tiles.get_isize(i - 1, j + 1).cloned(), | ||||
|             self.collision_tiles.get_isize(i    , j + 1).cloned(), | ||||
|             self.collision_tiles.get_isize(i + 1, j + 1).cloned(), | ||||
|             self.collision_tiles.get_isize(i + 1, j    ).cloned(), | ||||
|             self.collision_tiles.get_isize(i + 1, j - 1).cloned(), | ||||
|             self.collision_tiles.get_isize(i    , j - 1).cloned(), | ||||
|         ] | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the graphic tile corresponding to the collision tiles.
 | ||||
|     pub fn graphic_tile(&self, i: usize, j: usize) -> GraphicTile { | ||||
|         if self.tiles[(i, j)].0 == CollisionTile::full() { | ||||
|             GraphicTile::from_neighbour_options( | ||||
|                 self.tiles.get(((i - 1) as usize, (j - 1) as usize)).map(|x| x.0), | ||||
|                 self.tiles.get(((i - 1) as usize, (j    ) as usize)).map(|x| x.0), | ||||
|                 self.tiles.get(((i - 1) as usize, (j + 1) as usize)).map(|x| x.0), | ||||
|                 self.tiles.get(((i    ) as usize, (j + 1) as usize)).map(|x| x.0), | ||||
|                 self.tiles.get(((i + 1) as usize, (j + 1) as usize)).map(|x| x.0), | ||||
|                 self.tiles.get(((i + 1) as usize, (j    ) as usize)).map(|x| x.0), | ||||
|                 self.tiles.get(((i + 1) as usize, (j - 1) as usize)).map(|x| x.0), | ||||
|                 self.tiles.get(((i    ) as usize, (j - 1) as usize)).map(|x| x.0), | ||||
|             ) | ||||
|         if self.collision_tiles[(i, j)].is_full() { | ||||
|             GraphicTile::from_neighbour_options(&self.neighbours(i as isize, j as isize)) | ||||
|         } else { | ||||
|             GraphicTile(None) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a tile of the map.
 | ||||
|     pub fn tile(&self, i: usize, j: usize) -> Option<CollisionTile> { | ||||
|         self.tiles.get((i, j)).map(|x| x.0) | ||||
|     pub fn collision_tile(&self, i: usize, j: usize) -> Option<CollisionTile> { | ||||
|         self.collision_tiles.get((i, j)).cloned() | ||||
|     } | ||||
| 
 | ||||
|     /// Changes a tile of the map.
 | ||||
|     pub fn set_tile(&mut self, i: usize, j: usize, tile: CollisionTile) { | ||||
|         self.tiles[(i, j)] = (tile, GraphicTile(None)); | ||||
|         // Change the collision tile
 | ||||
|         self.collision_tiles[(i, j)] = tile; | ||||
| 
 | ||||
|         // Refresh the current graphic tile and their neighbours
 | ||||
|         for i in (i - 1) ..= (i + 1) { | ||||
|             for j in (j - 1) ..= (j + 1) { | ||||
|                 if self.tiles.get((i, j)).is_some() { | ||||
|                     self.tiles[(i, j)].1 = self.graphic_tile(i, j); | ||||
|                 let new_tile = self.graphic_tile(i, j); | ||||
|                 if let Some(tile) = self.graphic_tiles.get_mut((i, j)) { | ||||
|                     *tile = new_tile; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Finds a possible entrance.
 | ||||
|     pub fn find_entrance(tiles: &Matrix<(CollisionTile, GraphicTile)>) -> (usize, usize) { | ||||
|     pub fn find_entrance(tiles: &Matrix<CollisionTile>) -> (usize, usize) { | ||||
|         (tiles.rows() - 5, 1) | ||||
|     } | ||||
| 
 | ||||
| @ -349,20 +359,20 @@ impl Map { | ||||
|     /// Returns an iterator to the positioned tiles.
 | ||||
|     pub fn at(&self, row: usize, col: usize) -> PositionedTile { | ||||
|         PositionedTile { | ||||
|             collision: self.tiles[(row, col)].0, | ||||
|             graphic: self.tiles[(row, col)].1, | ||||
|             collision: self.collision_tiles[(row, col)], | ||||
|             graphic: self.graphic_tiles[(row, col)], | ||||
|             position: (col as f32 * SPRITE_SIZE_F32, row as f32 * SPRITE_SIZE_F32), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the number of rows of the map.
 | ||||
|     pub fn rows(&self) -> usize { | ||||
|         self.tiles.rows() | ||||
|         self.collision_tiles.rows() | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the number of columns of the map.
 | ||||
|     pub fn cols(&self) -> usize { | ||||
|         self.tiles.cols() | ||||
|         self.collision_tiles.cols() | ||||
|     } | ||||
| 
 | ||||
|     /// Checks whether the bounding box collides with elements of the map.
 | ||||
| @ -376,8 +386,8 @@ impl Map { | ||||
| 
 | ||||
|         let mut damage = Damage::None; | ||||
| 
 | ||||
|         let cols = self.tiles.cols() - 1; | ||||
|         let rows = self.tiles.rows() - 1; | ||||
|         let cols = self.collision_tiles.cols() - 1; | ||||
|         let rows = self.collision_tiles.rows() - 1; | ||||
| 
 | ||||
|         let min_col = clamp(new.left / SPRITE_SIZE_F32, 0.0, cols as f32) as usize; | ||||
|         let min_row = clamp(new.top / SPRITE_SIZE_F32, 0.0, rows as f32) as usize; | ||||
| @ -401,7 +411,7 @@ impl Map { | ||||
|                 } | ||||
| 
 | ||||
|                 // Collisions between feet and ground
 | ||||
|                 if self.tiles[(row, col)].0.from_top | ||||
|                 if self.collision_tiles[(row, col)].from_top | ||||
|                     && old.top + old.height <= tile_top | ||||
|                     && new.top + new.height >= tile_top | ||||
|                 { | ||||
| @ -414,7 +424,7 @@ impl Map { | ||||
|                 } | ||||
| 
 | ||||
|                 // Collisions between right and right wall
 | ||||
|                 if self.tiles[(row, col)].0.from_left | ||||
|                 if self.collision_tiles[(row, col)].from_left | ||||
|                     && old.left + old.width <= tile_left | ||||
|                     && new.left + new.width >= tile_left | ||||
|                 { | ||||
| @ -427,7 +437,7 @@ impl Map { | ||||
|                 } | ||||
| 
 | ||||
|                 // Collisions between left and left wall
 | ||||
|                 if self.tiles[(row, col)].0.from_right | ||||
|                 if self.collision_tiles[(row, col)].from_right | ||||
|                     && old.left >= tile_left + SPRITE_SIZE_F32 | ||||
|                     && new.left <= tile_left + SPRITE_SIZE_F32 | ||||
|                 { | ||||
| @ -440,7 +450,7 @@ impl Map { | ||||
|                 } | ||||
| 
 | ||||
|                 // Collisions between head and roof
 | ||||
|                 if self.tiles[(row, col)].0.from_bottom | ||||
|                 if self.collision_tiles[(row, col)].from_bottom | ||||
|                     && old.top >= tile_top + SPRITE_SIZE_F32 | ||||
|                     && new.top <= tile_top + SPRITE_SIZE_F32 | ||||
|                 { | ||||
| @ -463,8 +473,8 @@ impl Map { | ||||
|         } | ||||
| 
 | ||||
|         // Collision between the player and the void
 | ||||
|         if new.top > self.tiles.rows() as f32 * SPRITE_SIZE_F32 { | ||||
|             new.top = self.tiles.rows() as f32 * SPRITE_SIZE_F32; | ||||
|         if new.top > self.collision_tiles.rows() as f32 * SPRITE_SIZE_F32 { | ||||
|             new.top = self.collision_tiles.rows() as f32 * SPRITE_SIZE_F32; | ||||
|             collision_y = true; | ||||
|             damage = Damage::Death; | ||||
|         } | ||||
|  | ||||
| @ -27,7 +27,7 @@ pub fn duration_as_f32(duration: &Duration) -> f32 { | ||||
| } | ||||
| 
 | ||||
| /// A generic matrix type, useful for levels.
 | ||||
| #[derive(Serialize, Deserialize)] | ||||
| #[derive(Serialize, Deserialize, Clone)] | ||||
| pub struct Matrix<T> { | ||||
|     /// The number of rows of the matrix.
 | ||||
|     rows: usize, | ||||
| @ -77,6 +77,25 @@ impl<T> Matrix<T> { | ||||
|             None | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /// Returns the tile if any, none otherwise.
 | ||||
|     pub fn get_isize(&self, row: isize, col: isize) -> Option<&T> { | ||||
|         if row >= 0 && col >= 0 && (row as usize) < self.rows && (col as usize) < self.cols { | ||||
|             Some(&self[(row as usize, col as usize)]) | ||||
|         } else { | ||||
|             None | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a mutable reference to the tile if any.
 | ||||
|     pub fn get_mut(&mut self, (row, col): (usize, usize)) -> Option<&mut T> { | ||||
|         if row < self.rows && col < self.cols { | ||||
|             Some(&mut self[(row, col)]) | ||||
|         } else { | ||||
|             None | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> Index<(usize, usize)> for Matrix<T> { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user