Up stairs & down stairs
This commit is contained in:
parent
411b8091f9
commit
0ec5fbbe8c
37
src/game.rs
37
src/game.rs
|
@ -29,6 +29,12 @@ pub const LEVEL_SIZE: (usize, usize) = (80, 24);
|
|||
pub struct DungeonLevel {
|
||||
/// The tiles at every position in the level.
|
||||
tiles: [[DungeonTile; LEVEL_SIZE.0]; LEVEL_SIZE.1],
|
||||
|
||||
/// The location of each of the up-staircases.
|
||||
upstairs: Vec<(i32, i32)>,
|
||||
|
||||
/// The location of each of the down-staircases.
|
||||
downstairs: Vec<(i32, i32)>,
|
||||
}
|
||||
|
||||
/// The smallest measurable independent location in the dungeon,
|
||||
|
@ -38,14 +44,31 @@ pub enum DungeonTile {
|
|||
Floor,
|
||||
Wall,
|
||||
Hallway,
|
||||
Upstair,
|
||||
Downstair,
|
||||
}
|
||||
|
||||
impl DungeonLevel {
|
||||
/// Creates a new level in a branch that has the given
|
||||
/// configuration.
|
||||
pub fn new(_cfg: &BranchConfig) -> Self {
|
||||
// Self {
|
||||
// tiles: rooms::generate_level(100, &mut rand::thread_rng()),
|
||||
// }
|
||||
rooms::generate_level(100, &mut rand::thread_rng(), 1, 1)
|
||||
}
|
||||
|
||||
/// Creates a new level with the given set of tiles, upstairs, and
|
||||
/// downstairs.
|
||||
pub fn from_raw_parts(
|
||||
tiles: [[DungeonTile; LEVEL_SIZE.0]; LEVEL_SIZE.1],
|
||||
upstairs: Vec<(i32, i32)>,
|
||||
downstairs: Vec<(i32, i32)>,
|
||||
) -> Self {
|
||||
Self {
|
||||
tiles: rooms::generate_level(100, &mut rand::thread_rng()),
|
||||
tiles,
|
||||
upstairs,
|
||||
downstairs,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +123,8 @@ impl DungeonLevel {
|
|||
}
|
||||
}
|
||||
DungeonTile::Hallway => '#',
|
||||
DungeonTile::Upstair => '<',
|
||||
DungeonTile::Downstair => '>',
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,6 +133,16 @@ impl DungeonLevel {
|
|||
pub fn tile(&self, x: i32, y: i32) -> &DungeonTile {
|
||||
&self.tiles[y as usize][x as usize]
|
||||
}
|
||||
|
||||
/// Gets the list of up-stairs.
|
||||
pub fn upstairs(&self) -> &[(i32, i32)] {
|
||||
&self.upstairs
|
||||
}
|
||||
|
||||
/// Gets the list of down-stairs.
|
||||
pub fn downstairs(&self) -> &[(i32, i32)] {
|
||||
&self.downstairs
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for DungeonLevel {
|
||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -22,12 +22,13 @@ fn main() {
|
|||
|
||||
let cfg = BranchConfig;
|
||||
let level = DungeonLevel::new(&cfg);
|
||||
let spawn_pos = level.upstairs()[0];
|
||||
|
||||
world.insert(level);
|
||||
|
||||
world
|
||||
.create_entity()
|
||||
.with(Position { x: 5, y: 6 })
|
||||
.with(Position { x: spawn_pos.0, y: spawn_pos.1 })
|
||||
.with(CharRender { glyph: '@' })
|
||||
.with(Player)
|
||||
.with(Mobile {
|
||||
|
@ -49,16 +50,14 @@ fn main() {
|
|||
loop {
|
||||
dispatcher.dispatch(&world);
|
||||
|
||||
let players = world.read_storage::<Player>();
|
||||
let turns = world.read_storage::<TurnTaker>();
|
||||
|
||||
if (&players, &turns).join().any(|(_plr, turn)| turn.next == 0) {
|
||||
drop(players);
|
||||
drop(turns);
|
||||
if (
|
||||
&world.read_storage::<Player>(),
|
||||
&world.read_storage::<TurnTaker>(),
|
||||
)
|
||||
.join()
|
||||
.any(|(_plr, turn)| turn.next == 0)
|
||||
{
|
||||
player_turn(&mut world, &mut window);
|
||||
} else {
|
||||
drop(players);
|
||||
drop(turns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
63
src/rooms.rs
63
src/rooms.rs
|
@ -20,7 +20,7 @@ use pathfinding::directed::astar::astar;
|
|||
use rand::Rng;
|
||||
|
||||
use crate::{
|
||||
game::{DungeonTile, LEVEL_SIZE},
|
||||
game::{DungeonLevel, DungeonTile, LEVEL_SIZE},
|
||||
util::NiceFloat,
|
||||
};
|
||||
|
||||
|
@ -48,7 +48,13 @@ const HALLWAY_RANDOMNESS: f64 = 0.6;
|
|||
|
||||
/// Generates a grid of the given size containing rooms connected by
|
||||
/// passages.
|
||||
pub fn generate(n_rooms: usize, size: (usize, usize), rng: &mut impl Rng) -> Grid<DungeonTile> {
|
||||
pub fn generate(
|
||||
n_rooms: usize,
|
||||
size: (usize, usize),
|
||||
rng: &mut impl Rng,
|
||||
upstairs: usize,
|
||||
downstairs: usize,
|
||||
) -> (Grid<DungeonTile>, Vec<(i32, i32)>, Vec<(i32, i32)>) {
|
||||
let mut grid = Grid::init(size.1, size.0, DungeonTile::Wall);
|
||||
let rooms = RoomBounds::generate(n_rooms, size, rng);
|
||||
|
||||
|
@ -58,21 +64,24 @@ pub fn generate(n_rooms: usize, size: (usize, usize), rng: &mut impl Rng) -> Gri
|
|||
}
|
||||
}
|
||||
|
||||
cut_hallways(&mut grid, &rooms, rng);
|
||||
add_hallways(&mut grid, &rooms, rng);
|
||||
let (upstairs, downstairs) = add_stairs(&mut grid, upstairs, downstairs, rng);
|
||||
|
||||
grid
|
||||
(grid, upstairs, downstairs)
|
||||
}
|
||||
|
||||
/// Generates a grid of the statically-known level size.
|
||||
pub fn generate_level(
|
||||
n_rooms: usize,
|
||||
rng: &mut impl Rng,
|
||||
) -> [[DungeonTile; LEVEL_SIZE.0]; LEVEL_SIZE.1] {
|
||||
upstairs: usize,
|
||||
downstairs: usize,
|
||||
) -> DungeonLevel {
|
||||
// FIXME: This function is atrocious. We do an allocation here
|
||||
// when we theoretically doesn't need to (we get a heap-allocated
|
||||
// Grid back, when we know statically that it's LEVEL_SIZE so we
|
||||
// could allocate it on the stack)...
|
||||
let grid = generate(n_rooms, LEVEL_SIZE, rng);
|
||||
let (grid, upstairs, downstairs) = generate(n_rooms, LEVEL_SIZE, rng, upstairs, downstairs);
|
||||
|
||||
// ...and then we use a pointless default of DungeonTile::Floor
|
||||
// here then copy in the real data from `grid`.
|
||||
|
@ -84,7 +93,7 @@ pub fn generate_level(
|
|||
*slot = value;
|
||||
}
|
||||
|
||||
data
|
||||
DungeonLevel::from_raw_parts(data, upstairs, downstairs)
|
||||
}
|
||||
|
||||
/// The bounding box of a room.
|
||||
|
@ -171,7 +180,7 @@ impl RoomBounds {
|
|||
}
|
||||
|
||||
/// Adds a set of hallways connecting the given rooms to a dungeon.
|
||||
fn cut_hallways(grid: &mut Grid<DungeonTile>, rooms: &[RoomBounds], rng: &mut impl Rng) {
|
||||
fn add_hallways(grid: &mut Grid<DungeonTile>, rooms: &[RoomBounds], rng: &mut impl Rng) {
|
||||
// How hard we try to avoid traveling through stone at a pair of
|
||||
// coordinates.
|
||||
let mut stone_weights = Grid::new(grid.rows(), grid.cols());
|
||||
|
@ -239,3 +248,41 @@ fn cut_hallways(grid: &mut Grid<DungeonTile>, rooms: &[RoomBounds], rng: &mut im
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds staircases leading upwards and downwards to the level.
|
||||
fn add_stairs(
|
||||
grid: &mut Grid<DungeonTile>,
|
||||
n_upstairs: usize,
|
||||
n_downstairs: usize,
|
||||
rng: &mut impl Rng,
|
||||
) -> (Vec<(i32, i32)>, Vec<(i32, i32)>) {
|
||||
let (mut upstairs, mut downstairs) = (
|
||||
Vec::with_capacity(n_upstairs),
|
||||
Vec::with_capacity(n_downstairs),
|
||||
);
|
||||
|
||||
for _ in 0..n_upstairs {
|
||||
let (x, y) = empty_square(grid, rng);
|
||||
upstairs.push((x, y));
|
||||
grid[y as usize][x as usize] = DungeonTile::Upstair;
|
||||
}
|
||||
|
||||
for _ in 0..n_downstairs {
|
||||
let (x, y) = empty_square(grid, rng);
|
||||
downstairs.push((x, y));
|
||||
grid[y as usize][x as usize] = DungeonTile::Downstair;
|
||||
}
|
||||
|
||||
(upstairs, downstairs)
|
||||
}
|
||||
|
||||
/// Finds an unoccupied (floor) square of the level.
|
||||
fn empty_square(grid: &Grid<DungeonTile>, rng: &mut impl Rng) -> (i32, i32) {
|
||||
loop {
|
||||
let (x, y) = (rng.gen_range(0..grid.cols()), rng.gen_range(0..grid.rows()));
|
||||
|
||||
if grid[y][x] == DungeonTile::Floor {
|
||||
break (x as _, y as _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue