Work on restructuring world generator API

We need to be able to spawn entities from the generator function, both
as level props and as enemies; the previous API makes this impossible,
so I'm working on restructuring it. Not too happy with it yet, still
needs more work.
This commit is contained in:
Alex Bethel 2022-01-15 14:49:15 -06:00
parent 652db1241b
commit aa7361df6b
3 changed files with 47 additions and 25 deletions

View file

@ -1,22 +1,35 @@
use std::fmt::Display;
use pancurses::Window;
use rand::{thread_rng, Rng};
use specs::prelude::*;
use crate::rooms;
use crate::{
components::{CharRender, Position},
rooms,
};
/// The size of a dungeon level, in tiles.
pub const LEVEL_SIZE: (usize, usize) = (80, 24);
/// A single level of the dungeon.
#[derive(Clone)]
pub struct DungeonLevel {
/// The tiles at every position in the level.
tiles: [[DungeonTile; LEVEL_SIZE.0]; LEVEL_SIZE.1],
/// The locations of the level's exits.
exits: LevelExits,
}
/// The entrances and exits from a level.
#[derive(Clone)]
pub struct LevelExits {
/// The location of each of the up-staircases.
upstairs: Vec<(i32, i32)>,
pub upstairs: Vec<(i32, i32)>,
/// The location of each of the down-staircases.
downstairs: Vec<(i32, i32)>,
pub downstairs: Vec<(i32, i32)>,
}
/// The smallest measurable independent location in the dungeon,
@ -49,26 +62,45 @@ impl DungeonTile {
}
impl DungeonLevel {
/// Creates a new level in a branch that has the given
/// configuration.
pub fn new() -> Self {
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(
pub fn new(
tiles: [[DungeonTile; LEVEL_SIZE.0]; LEVEL_SIZE.1],
upstairs: Vec<(i32, i32)>,
downstairs: Vec<(i32, i32)>,
) -> Self {
Self {
tiles,
upstairs,
downstairs,
exits: LevelExits {
upstairs,
downstairs,
},
}
}
/// Creates a new level and registers it with the given world.
pub fn generate_level(world: &mut World) -> LevelExits {
let level = rooms::generate_level(100, &mut thread_rng(), 1, 1);
world.insert(level.clone()); // inefficient but whatever
// Spawn some zombies in the world.
for _ in 0..20 {
let (x, y) = (
thread_rng().gen_range(0..LEVEL_SIZE.0 as _),
thread_rng().gen_range(0..LEVEL_SIZE.1 as _),
);
if level.tile(x, y).is_navigable() {
world
.create_entity()
.with(Position { x, y })
.with(CharRender { glyph: 'Z' })
.build();
}
}
level.exits
}
/// Draws a level on the display window.
pub fn draw(&self, win: &Window) {
for y in 0..LEVEL_SIZE.1 {
@ -130,16 +162,6 @@ 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 {

View file

@ -20,8 +20,8 @@ fn main() {
register_all(&mut world);
let level = DungeonLevel::new();
let spawn_pos = level.upstairs()[0];
let level = DungeonLevel::generate_level(&mut world);
let spawn_pos = level.upstairs[0];
world.insert(level);

View file

@ -93,7 +93,7 @@ pub fn generate_level(
*slot = value;
}
DungeonLevel::from_raw_parts(data, upstairs, downstairs)
DungeonLevel::new(data, upstairs, downstairs)
}
/// The bounding box of a room.