room builders
This commit is contained in:
parent
2ceb20a822
commit
46e0c6ec6b
5 changed files with 108 additions and 20 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{apply_room_to_map, draw_corridor, BuilderMap, InitialMapBuilder, Map, Rect, TileType};
|
use super::{BuilderMap, InitialMapBuilder, Map, Rect, TileType};
|
||||||
use rltk::RandomNumberGenerator;
|
use rltk::RandomNumberGenerator;
|
||||||
|
|
||||||
pub struct BspDungeonBuilder {
|
pub struct BspDungeonBuilder {
|
||||||
|
|
@ -32,11 +32,9 @@ impl BspDungeonBuilder {
|
||||||
let rect = self.get_random_rect(rng);
|
let rect = self.get_random_rect(rng);
|
||||||
let candidate = self.get_random_sub_rect(rect, rng);
|
let candidate = self.get_random_sub_rect(rect, rng);
|
||||||
|
|
||||||
if self.is_possible(candidate, &build_data.map) {
|
if self.is_possible(candidate, &build_data, &rooms) {
|
||||||
apply_room_to_map(&mut build_data.map, &candidate);
|
|
||||||
rooms.push(candidate);
|
rooms.push(candidate);
|
||||||
self.add_subrects(rect);
|
self.add_subrects(rect);
|
||||||
build_data.take_snapshot();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n_rooms += 1;
|
n_rooms += 1;
|
||||||
|
|
@ -81,7 +79,7 @@ impl BspDungeonBuilder {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_possible(&self, rect: Rect, map: &Map) -> bool {
|
fn is_possible(&self, rect: Rect, build_data: &BuilderMap, rooms: &Vec<Rect>) -> bool {
|
||||||
let mut expanded = rect;
|
let mut expanded = rect;
|
||||||
expanded.x1 -= 2;
|
expanded.x1 -= 2;
|
||||||
expanded.x2 += 2;
|
expanded.x2 += 2;
|
||||||
|
|
@ -90,12 +88,18 @@ impl BspDungeonBuilder {
|
||||||
|
|
||||||
let mut can_build = true;
|
let mut can_build = true;
|
||||||
|
|
||||||
|
for r in rooms.iter() {
|
||||||
|
if r.intersect(&rect) {
|
||||||
|
can_build = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for y in expanded.y1..=expanded.y2 {
|
for y in expanded.y1..=expanded.y2 {
|
||||||
for x in expanded.x1..=expanded.x2 {
|
for x in expanded.x1..=expanded.x2 {
|
||||||
if x > map.width - 2 {
|
if x > build_data.map.width - 2 {
|
||||||
can_build = false;
|
can_build = false;
|
||||||
}
|
}
|
||||||
if y > map.height - 2 {
|
if y > build_data.map.height - 2 {
|
||||||
can_build = false;
|
can_build = false;
|
||||||
}
|
}
|
||||||
if x < 1 {
|
if x < 1 {
|
||||||
|
|
@ -105,14 +109,14 @@ impl BspDungeonBuilder {
|
||||||
can_build = false;
|
can_build = false;
|
||||||
}
|
}
|
||||||
if can_build {
|
if can_build {
|
||||||
let idx = map.xy_idx(x, y);
|
let idx = build_data.map.xy_idx(x, y);
|
||||||
if map.tiles[idx] != TileType::Wall {
|
if build_data.map.tiles[idx] != TileType::Wall {
|
||||||
can_build = false;
|
can_build = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
can_build
|
return can_build;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ mod rooms_corridors_bsp;
|
||||||
use rooms_corridors_bsp::BspCorridors;
|
use rooms_corridors_bsp::BspCorridors;
|
||||||
mod room_sorter;
|
mod room_sorter;
|
||||||
use room_sorter::{RoomSort, RoomSorter};
|
use room_sorter::{RoomSort, RoomSorter};
|
||||||
|
mod room_draw;
|
||||||
|
use room_draw::RoomDrawer;
|
||||||
|
|
||||||
// Shared data to be passed around build chain
|
// Shared data to be passed around build chain
|
||||||
pub struct BuilderMap {
|
pub struct BuilderMap {
|
||||||
|
|
@ -172,6 +174,14 @@ fn random_room_builder(rng: &mut rltk::RandomNumberGenerator, builder: &mut Buil
|
||||||
_ => builder.with(RoomSorter::new(RoomSort::CENTRAL)),
|
_ => builder.with(RoomSorter::new(RoomSort::CENTRAL)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.with(RoomDrawer::new());
|
||||||
|
|
||||||
|
let corridor_roll = rng.roll_dice(1, 2);
|
||||||
|
match corridor_roll {
|
||||||
|
1 => builder.with(DoglegCorridors::new()),
|
||||||
|
_ => builder.with(BspCorridors::new()),
|
||||||
|
}
|
||||||
|
|
||||||
let corridor_roll = rng.roll_dice(1, 2);
|
let corridor_roll = rng.roll_dice(1, 2);
|
||||||
match corridor_roll {
|
match corridor_roll {
|
||||||
1 => builder.with(DoglegCorridors::new()),
|
1 => builder.with(DoglegCorridors::new()),
|
||||||
|
|
@ -252,11 +262,9 @@ pub fn random_builder(new_depth: i32, rng: &mut rltk::RandomNumberGenerator) ->
|
||||||
_ => random_shape_builder(rng, &mut builder),
|
_ => random_shape_builder(rng, &mut builder),
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WFC needs some fixes.
|
/*if rng.roll_dice(1, 3)==1 {
|
||||||
if rng.roll_dice(1, 3) == 1 {
|
builder.with(WaveformCollapseBuilder::new());
|
||||||
builder.with(WaveFunctionCollapseBuilder::new());
|
}*/
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if rng.roll_dice(1, 20) == 1 {
|
if rng.roll_dice(1, 20) == 1 {
|
||||||
builder.with(PrefabBuilder::sectional(prefab_builder::prefab_sections::UNDERGROUND_FORT));
|
builder.with(PrefabBuilder::sectional(prefab_builder::prefab_sections::UNDERGROUND_FORT));
|
||||||
|
|
|
||||||
62
src/map_builders/room_draw.rs
Normal file
62
src/map_builders/room_draw.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
use super::{BuilderMap, MetaMapBuilder, Rect, TileType};
|
||||||
|
use rltk::RandomNumberGenerator;
|
||||||
|
|
||||||
|
pub struct RoomDrawer {}
|
||||||
|
|
||||||
|
impl MetaMapBuilder for RoomDrawer {
|
||||||
|
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
self.build(rng, build_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RoomDrawer {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new() -> Box<RoomDrawer> {
|
||||||
|
return Box::new(RoomDrawer {});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rectangle(&mut self, build_data: &mut BuilderMap, room: &Rect) {
|
||||||
|
for y in room.y1 + 1..=room.y2 {
|
||||||
|
for x in room.x1 + 1..=room.x2 {
|
||||||
|
let idx = build_data.map.xy_idx(x, y);
|
||||||
|
if idx > 0 && idx < ((build_data.map.width * build_data.map.height) - 1) as usize {
|
||||||
|
build_data.map.tiles[idx] = TileType::Floor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn circle(&mut self, build_data: &mut BuilderMap, room: &Rect) {
|
||||||
|
let radius = i32::min(room.x2 - room.x1, room.y2 - room.y1) as f32 / 2.0;
|
||||||
|
let center = room.centre();
|
||||||
|
let center_pt = rltk::Point::new(center.0, center.1);
|
||||||
|
for y in room.y1..=room.y2 {
|
||||||
|
for x in room.x1..=room.x2 {
|
||||||
|
let idx = build_data.map.xy_idx(x, y);
|
||||||
|
let distance = rltk::DistanceAlg::Pythagoras.distance2d(center_pt, rltk::Point::new(x, y));
|
||||||
|
if idx > 0 && idx < ((build_data.map.width * build_data.map.height) - 1) as usize && distance <= radius
|
||||||
|
{
|
||||||
|
build_data.map.tiles[idx] = TileType::Floor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||||
|
let rooms: Vec<Rect>;
|
||||||
|
if let Some(rooms_builder) = &build_data.rooms {
|
||||||
|
rooms = rooms_builder.clone();
|
||||||
|
} else {
|
||||||
|
panic!("Room Drawing require a builder with room structures");
|
||||||
|
}
|
||||||
|
|
||||||
|
for room in rooms.iter() {
|
||||||
|
let room_type = rng.roll_dice(1, 4);
|
||||||
|
match room_type {
|
||||||
|
1 => self.circle(build_data, room),
|
||||||
|
_ => self.rectangle(build_data, room),
|
||||||
|
}
|
||||||
|
build_data.take_snapshot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -35,11 +35,7 @@ impl SimpleMapBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ok {
|
if ok {
|
||||||
apply_room_to_map(&mut build_data.map, &new_room);
|
|
||||||
build_data.take_snapshot();
|
|
||||||
|
|
||||||
rooms.push(new_room);
|
rooms.push(new_room);
|
||||||
build_data.take_snapshot();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
build_data.rooms = Some(rooms);
|
build_data.rooms = Some(rooms);
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,7 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
|
||||||
"confusion wand" => confusion_wand(ecs, x, y),
|
"confusion wand" => confusion_wand(ecs, x, y),
|
||||||
// Food
|
// Food
|
||||||
"rations" => rations(ecs, x, y),
|
"rations" => rations(ecs, x, y),
|
||||||
|
"apple" => apple(ecs, x, y),
|
||||||
// Traps
|
// Traps
|
||||||
"bear trap" => bear_trap(ecs, x, y),
|
"bear trap" => bear_trap(ecs, x, y),
|
||||||
"confusion trap" => confusion_trap(ecs, x, y),
|
"confusion trap" => confusion_trap(ecs, x, y),
|
||||||
|
|
@ -220,7 +221,7 @@ fn item_table(_map_depth: i32) -> RandomTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn food_table(_map_depth: i32) -> RandomTable {
|
fn food_table(_map_depth: i32) -> RandomTable {
|
||||||
return RandomTable::new().add("rations", 1);
|
return RandomTable::new().add("rations", 1).add("apple", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trap_table(_map_depth: i32) -> RandomTable {
|
fn trap_table(_map_depth: i32) -> RandomTable {
|
||||||
|
|
@ -492,6 +493,23 @@ fn rations(ecs: &mut World, x: i32, y: i32) {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn apple(ecs: &mut World, x: i32, y: i32) {
|
||||||
|
ecs.create_entity()
|
||||||
|
.with(Position { x, y })
|
||||||
|
.with(Renderable {
|
||||||
|
glyph: rltk::to_cp437('%'),
|
||||||
|
fg: RGB::named(rltk::GREEN),
|
||||||
|
bg: RGB::named(rltk::BLACK),
|
||||||
|
render_order: 2,
|
||||||
|
})
|
||||||
|
.with(Name { name: "apple".to_string(), plural: "apples".to_string() })
|
||||||
|
.with(Item {})
|
||||||
|
.with(ProvidesNutrition {})
|
||||||
|
.with(Consumable {})
|
||||||
|
.marked::<SimpleMarker<SerializeMe>>()
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
// WANDS
|
// WANDS
|
||||||
|
|
||||||
fn fireball_wand(ecs: &mut World, x: i32, y: i32) {
|
fn fireball_wand(ecs: &mut World, x: i32, y: i32) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue