map.rs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. use rand::Rng;
  2. use specs::prelude::*;
  3. #[derive(PartialEq, Clone, Copy, Debug)]
  4. pub enum TileType {
  5. Wall,
  6. Floor,
  7. }
  8. impl TileType {
  9. pub fn glyph(&self) -> carpet::CP437 {
  10. match self {
  11. TileType::Wall => carpet::CP437::from_char('#'),
  12. TileType::Floor => carpet::CP437::from_u8(0),
  13. }
  14. }
  15. pub fn blocks_view(&self) -> bool {
  16. match self {
  17. TileType::Wall => true,
  18. TileType::Floor => false,
  19. }
  20. }
  21. }
  22. pub struct Map {
  23. pub tiles: carpet::Board<TileType>,
  24. pub rooms: Vec<carpet::Rect>,
  25. }
  26. impl Map {
  27. pub fn new() -> Map {
  28. let mut rng = rand::thread_rng();
  29. let mut map = Map {
  30. tiles: carpet::Board::new_with_default(80, 50, TileType::Wall),
  31. rooms: Vec::new(),
  32. };
  33. const MAX_ROOMS: usize = 30;
  34. const MIN_SIZE: usize = 6;
  35. const MAX_SIZE: usize = 10;
  36. for _ in 0..MAX_ROOMS {
  37. let w = rng.gen_range(MIN_SIZE..MAX_SIZE);
  38. let h = rng.gen_range(MIN_SIZE..MAX_SIZE);
  39. let x = rng.gen_range(1..80 - w);
  40. let y = rng.gen_range(1..50 - h);
  41. let room = carpet::Rect::new([x, y], [w, h]);
  42. if map.rooms.iter().any(|r| r.overlaps(room)) {
  43. continue;
  44. }
  45. map.carve(room);
  46. if let Some(prev) = map.rooms.first() {
  47. let c1 = room.center();
  48. let c2 = prev.center();
  49. let join = if rng.gen() {
  50. carpet::Coord { x: c1.x, y: c2.y }
  51. } else {
  52. carpet::Coord { x: c2.x, y: c1.y }
  53. };
  54. map.carve(carpet::Rect::from_points(c1, join));
  55. map.carve(carpet::Rect::from_points(join, c2));
  56. }
  57. map.rooms.push(room);
  58. }
  59. map
  60. }
  61. fn carve(&mut self, rect: carpet::Rect) {
  62. let iter = self
  63. .tiles
  64. .window_iter_mut(rect)
  65. .unwrap_or_else(|| panic!("Rect {:?} of map bounds", rect));
  66. for (_, _, t) in iter {
  67. *t = TileType::Floor;
  68. }
  69. }
  70. pub fn passable(&self, (x, y): (usize, usize)) -> bool {
  71. Some(&TileType::Floor) == self.tiles.get(x, y)
  72. }
  73. }
  74. #[derive(Component)]
  75. pub struct Viewshed {
  76. pub vs: carpet::Viewshed<TileType>,
  77. pub dirty: bool,
  78. }