|
@@ -24,21 +24,55 @@ impl TileType {
|
|
|
|
|
|
pub struct Map {
|
|
|
tiles: carpet::Board<TileType>,
|
|
|
+ rooms: Vec<carpet::Rect>,
|
|
|
}
|
|
|
|
|
|
impl Map {
|
|
|
fn new() -> Map {
|
|
|
let mut rng = rand::thread_rng();
|
|
|
- let tiles = carpet::Board::new_from(80, 50, |x, y| {
|
|
|
- if x == 0 || x == 79 || y == 0 || y == 49 {
|
|
|
- TileType::Wall
|
|
|
- } else if rng.gen::<u8>() % 8 == 0 {
|
|
|
- TileType::Wall
|
|
|
- } else {
|
|
|
- TileType::Floor
|
|
|
+ let mut map = Map {
|
|
|
+ tiles: carpet::Board::new_with_default(80, 50, TileType::Wall),
|
|
|
+ rooms: Vec::new(),
|
|
|
+ };
|
|
|
+
|
|
|
+ const MAX_ROOMS: usize = 30;
|
|
|
+ const MIN_SIZE: usize = 6;
|
|
|
+ const MAX_SIZE: usize = 10;
|
|
|
+
|
|
|
+ for _ in 0..MAX_ROOMS {
|
|
|
+ let w = rng.gen_range(MIN_SIZE, MAX_SIZE);
|
|
|
+ let h = rng.gen_range(MIN_SIZE, MAX_SIZE);
|
|
|
+ let x = rng.gen_range(1, 80 - w);
|
|
|
+ let y = rng.gen_range(1, 50 - h);
|
|
|
+ let room = carpet::Rect::new([x, y], [w, h]);
|
|
|
+ if map.rooms.iter().any(|r| r.overlaps(room)) {
|
|
|
+ continue;
|
|
|
}
|
|
|
- });
|
|
|
- Map { tiles }
|
|
|
+ map.carve(room);
|
|
|
+ if let Some(prev) = map.rooms.first() {
|
|
|
+ let c1 = room.center();
|
|
|
+ let c2 = prev.center();
|
|
|
+ let join = if rng.gen() {
|
|
|
+ carpet::Coord { x: c1.x, y: c2.y }
|
|
|
+ } else {
|
|
|
+ carpet::Coord { x: c2.x, y: c1.y }
|
|
|
+ };
|
|
|
+ map.carve(carpet::Rect::from_points(c1, join));
|
|
|
+ map.carve(carpet::Rect::from_points(join, c2));
|
|
|
+ }
|
|
|
+
|
|
|
+ map.rooms.push(room);
|
|
|
+ }
|
|
|
+
|
|
|
+ map
|
|
|
+ }
|
|
|
+
|
|
|
+ fn carve(&mut self, rect: carpet::Rect) {
|
|
|
+ let iter = self.tiles.window_iter_mut(rect)
|
|
|
+ .expect(&format!("Rect {:?} of map bounds", rect));
|
|
|
+ for (_, _, t) in iter {
|
|
|
+ *t = TileType::Floor;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
fn passable(&self, (x, y): (usize, usize)) -> bool {
|
|
@@ -136,13 +170,15 @@ fn main() -> Result<(), GameError> {
|
|
|
game.register::<Motion>();
|
|
|
game.register::<Player>();
|
|
|
|
|
|
- game.insert(Map::new());
|
|
|
+ let map = Map::new();
|
|
|
+ let player_start = map.rooms.first().map(|r| r.center()).unwrap_or([40, 25].into());
|
|
|
+ game.insert(map);
|
|
|
|
|
|
game.create_entity()
|
|
|
- .with(Pos { x: 40, y: 25 })
|
|
|
+ .with(Pos { x: player_start.x, y: player_start.y })
|
|
|
.with(Player)
|
|
|
.with(Renderable {
|
|
|
- glyph: carpet::CP437::from_char('A'),
|
|
|
+ glyph: carpet::CP437::from_char('@'),
|
|
|
color: carpet::Color::Blue,
|
|
|
})
|
|
|
.build();
|