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 {
|
pub struct DungeonLevel {
|
||||||
/// The tiles at every position in the level.
|
/// The tiles at every position in the level.
|
||||||
tiles: [[DungeonTile; LEVEL_SIZE.0]; LEVEL_SIZE.1],
|
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,
|
/// The smallest measurable independent location in the dungeon,
|
||||||
|
@ -38,14 +44,31 @@ pub enum DungeonTile {
|
||||||
Floor,
|
Floor,
|
||||||
Wall,
|
Wall,
|
||||||
Hallway,
|
Hallway,
|
||||||
|
Upstair,
|
||||||
|
Downstair,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DungeonLevel {
|
impl DungeonLevel {
|
||||||
/// Creates a new level in a branch that has the given
|
/// Creates a new level in a branch that has the given
|
||||||
/// configuration.
|
/// configuration.
|
||||||
pub fn new(_cfg: &BranchConfig) -> Self {
|
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 {
|
Self {
|
||||||
tiles: rooms::generate_level(100, &mut rand::thread_rng()),
|
tiles,
|
||||||
|
upstairs,
|
||||||
|
downstairs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +123,8 @@ impl DungeonLevel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DungeonTile::Hallway => '#',
|
DungeonTile::Hallway => '#',
|
||||||
|
DungeonTile::Upstair => '<',
|
||||||
|
DungeonTile::Downstair => '>',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +133,16 @@ impl DungeonLevel {
|
||||||
pub fn tile(&self, x: i32, y: i32) -> &DungeonTile {
|
pub fn tile(&self, x: i32, y: i32) -> &DungeonTile {
|
||||||
&self.tiles[y as usize][x as usize]
|
&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 {
|
impl Display for DungeonLevel {
|
||||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -22,12 +22,13 @@ fn main() {
|
||||||
|
|
||||||
let cfg = BranchConfig;
|
let cfg = BranchConfig;
|
||||||
let level = DungeonLevel::new(&cfg);
|
let level = DungeonLevel::new(&cfg);
|
||||||
|
let spawn_pos = level.upstairs()[0];
|
||||||
|
|
||||||
world.insert(level);
|
world.insert(level);
|
||||||
|
|
||||||
world
|
world
|
||||||
.create_entity()
|
.create_entity()
|
||||||
.with(Position { x: 5, y: 6 })
|
.with(Position { x: spawn_pos.0, y: spawn_pos.1 })
|
||||||
.with(CharRender { glyph: '@' })
|
.with(CharRender { glyph: '@' })
|
||||||
.with(Player)
|
.with(Player)
|
||||||
.with(Mobile {
|
.with(Mobile {
|
||||||
|
@ -49,16 +50,14 @@ fn main() {
|
||||||
loop {
|
loop {
|
||||||
dispatcher.dispatch(&world);
|
dispatcher.dispatch(&world);
|
||||||
|
|
||||||
let players = world.read_storage::<Player>();
|
if (
|
||||||
let turns = world.read_storage::<TurnTaker>();
|
&world.read_storage::<Player>(),
|
||||||
|
&world.read_storage::<TurnTaker>(),
|
||||||
if (&players, &turns).join().any(|(_plr, turn)| turn.next == 0) {
|
)
|
||||||
drop(players);
|
.join()
|
||||||
drop(turns);
|
.any(|(_plr, turn)| turn.next == 0)
|
||||||
|
{
|
||||||
player_turn(&mut world, &mut window);
|
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 rand::Rng;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
game::{DungeonTile, LEVEL_SIZE},
|
game::{DungeonLevel, DungeonTile, LEVEL_SIZE},
|
||||||
util::NiceFloat,
|
util::NiceFloat,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,7 +48,13 @@ const HALLWAY_RANDOMNESS: f64 = 0.6;
|
||||||
|
|
||||||
/// Generates a grid of the given size containing rooms connected by
|
/// Generates a grid of the given size containing rooms connected by
|
||||||
/// passages.
|
/// 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 mut grid = Grid::init(size.1, size.0, DungeonTile::Wall);
|
||||||
let rooms = RoomBounds::generate(n_rooms, size, rng);
|
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.
|
/// Generates a grid of the statically-known level size.
|
||||||
pub fn generate_level(
|
pub fn generate_level(
|
||||||
n_rooms: usize,
|
n_rooms: usize,
|
||||||
rng: &mut impl Rng,
|
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
|
// FIXME: This function is atrocious. We do an allocation here
|
||||||
// when we theoretically doesn't need to (we get a heap-allocated
|
// 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
|
// Grid back, when we know statically that it's LEVEL_SIZE so we
|
||||||
// could allocate it on the stack)...
|
// 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
|
// ...and then we use a pointless default of DungeonTile::Floor
|
||||||
// here then copy in the real data from `grid`.
|
// here then copy in the real data from `grid`.
|
||||||
|
@ -84,7 +93,7 @@ pub fn generate_level(
|
||||||
*slot = value;
|
*slot = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
data
|
DungeonLevel::from_raw_parts(data, upstairs, downstairs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The bounding box of a room.
|
/// The bounding box of a room.
|
||||||
|
@ -171,7 +180,7 @@ impl RoomBounds {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a set of hallways connecting the given rooms to a dungeon.
|
/// 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
|
// How hard we try to avoid traveling through stone at a pair of
|
||||||
// coordinates.
|
// coordinates.
|
||||||
let mut stone_weights = Grid::new(grid.rows(), grid.cols());
|
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