Building a Dungeon

Learn how to place rooms randomly, connect them with corridors, and build a dungeon for the adventurer to explore.

Create a map builder module

Let’s create a new map_builder.rs file. This file contains the map building module. Add it to prelude in main.rs:

Press + to interact
mod map;
mod map_builder;
mod player;
mod prelude {
pub use bracket_lib::prelude::*;
pub const SCREEN_WIDTH: i32 = 80;
pub const SCREEN_HEIGHT: i32 = 50;
pub use crate::map::*;
pub use crate::player::*;
pub use crate::map_builder::*;
}

Start by importing the main prelude and defining a constant in map_builder.rs that represents the maximum number of rooms we’d like in our dungeon. 20 rooms produces a nice-looking dungeon.

Press + to interact
use crate::prelude::*;
const NUM_ROOMS: usize = 20

Define a new structure to hold the MapBuilder:

Press + to interact
pub struct MapBuilder {
pub map : Map,
pub rooms : Vec<Rect>,
pub player_start : Point,
}

The structure contains its own Map. It works on its own copy and passes the result to the game. The rooms vector is a list of the rooms that are added to the map. Each room is represented with the Rect structure from bracket-lib. The Rect structure is a helper for calculations involving rectangles. Finally, player_start stores the location at which the player enters the map.

Let’s start adding some details to the map.

Fill the map with walls

The previous example started with a dungeon composed entirely of floors. A room-carving algorithm works the other way around, starting with a solid block of rock and carving rooms and corridors from the stone.

Add the following to MapBuilder implementation:

Press + to interact
fn fill(&mut self, tile : TileType) {
self.map.tiles.iter_mut().for_each(|t| *t = tile);
}

This function obtains a mutable iterator with iter_mut() and then uses for_each() to ...