diff --git a/src/main.rs b/src/main.rs index 05bd033..829f514 100644 --- a/src/main.rs +++ b/src/main.rs @@ -142,23 +142,21 @@ impl State { } // Build new map - let worldmap; + let mut builder; let current_depth; let player_start; { let mut worldmap_resource = self.ecs.write_resource::(); current_depth = worldmap_resource.depth; let mut rng = self.ecs.write_resource::(); - let (newmap, start) = map_builders::build_random_map(&mut rng, current_depth + 1); - *worldmap_resource = newmap; - player_start = start; - worldmap = worldmap_resource.clone(); + builder = map_builders::random_builder(current_depth + 1); + builder.build_map(&mut rng); + *worldmap_resource = builder.get_map(); + player_start = builder.get_starting_pos(); } // Spawn things in rooms - for room in worldmap.rooms.iter().skip(1) { - spawner::spawn_room(&mut self.ecs, room, current_depth + 1); - } + builder.spawn_entities(&mut self.ecs); // Place the player and update resources let mut player_position = self.ecs.write_resource::(); @@ -198,21 +196,19 @@ impl State { } // Build a new map and place the player - let worldmap; + let mut builder; let player_start; { let mut worldmap_resource = self.ecs.write_resource::(); let mut rng = self.ecs.write_resource::(); - let (newmap, start) = map_builders::build_random_map(&mut rng, 1); - *worldmap_resource = newmap; - player_start = start; - worldmap = worldmap_resource.clone(); + builder = map_builders::random_builder(1); + builder.build_map(&mut rng); + *worldmap_resource = builder.get_map(); + player_start = builder.get_starting_pos(); } // Spawn bad guys - for room in worldmap.rooms.iter().skip(1) { - spawner::spawn_room(&mut self.ecs, room, 1); - } + builder.spawn_entities(&mut self.ecs); // Place the player and update resources let (player_x, player_y) = (player_start.x, player_start.y); @@ -533,16 +529,17 @@ fn main() -> rltk::BError { // Create seed. let mut rng = rltk::RandomNumberGenerator::new(); // Use seed to generate the map. - let (map, player_start) = map_builders::build_random_map(&mut rng, 1); + let mut builder = map_builders::random_builder(1); + builder.build_map(&mut rng); + let player_start = builder.get_starting_pos(); + let map = builder.get_map(); // Insert seed into the ECS. gs.ecs.insert(rng); let player_name = "wanderer".to_string(); let player_entity = spawner::player(&mut gs.ecs, player_start.x, player_start.y, player_name); - for room in map.rooms.iter().skip(1) { - spawner::spawn_room(&mut gs.ecs, room, 1); - } + builder.spawn_entities(&mut gs.ecs); gs.ecs.insert(map); gs.ecs.insert(Point::new(player_start.x, player_start.y)); diff --git a/src/map.rs b/src/map.rs index a0aec24..31d528a 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,4 +1,3 @@ -use super::Rect; use rltk::{Algorithm2D, BaseMap, Point, Rltk, RGB}; use serde::{Deserialize, Serialize}; use specs::prelude::*; @@ -19,7 +18,6 @@ pub const MAPCOUNT: usize = MAPHEIGHT * MAPWIDTH; #[derive(Default, Serialize, Deserialize, Clone)] pub struct Map { pub tiles: Vec, - pub rooms: Vec, pub width: i32, pub height: i32, pub revealed_tiles: Vec, @@ -46,7 +44,6 @@ impl Map { pub fn new(new_depth: i32) -> Map { Map { tiles: vec![TileType::Wall; MAPCOUNT], - rooms: Vec::new(), width: MAPWIDTH as i32, height: MAPHEIGHT as i32, revealed_tiles: vec![false; MAPCOUNT], diff --git a/src/map_builders/mod.rs b/src/map_builders/mod.rs index 5bf7e33..03653f2 100644 --- a/src/map_builders/mod.rs +++ b/src/map_builders/mod.rs @@ -6,10 +6,13 @@ use common::*; use rltk::RandomNumberGenerator; use specs::prelude::*; -trait MapBuilder { - fn build(rng: &mut RandomNumberGenerator, new_depth: i32) -> (Map, Position); +pub trait MapBuilder { + fn build_map(&mut self, rng: &mut RandomNumberGenerator); + fn spawn_entities(&mut self, ecs: &mut World); + fn get_map(&mut self) -> Map; + fn get_starting_pos(&mut self) -> Position; } -pub fn build_random_map(rng: &mut RandomNumberGenerator, new_depth: i32) -> (Map, Position) { - SimpleMapBuilder::build(rng, new_depth) +pub fn random_builder(new_depth: i32) -> Box { + return Box::new(SimpleMapBuilder::new(new_depth)); } diff --git a/src/map_builders/simple_map.rs b/src/map_builders/simple_map.rs index 76a9258..2151e52 100644 --- a/src/map_builders/simple_map.rs +++ b/src/map_builders/simple_map.rs @@ -5,73 +5,98 @@ use super::{ use rltk::RandomNumberGenerator; use specs::prelude::*; -pub struct SimpleMapBuilder {} +pub struct SimpleMapBuilder { + map: Map, + starting_position: Position, + depth: i32, + rooms: Vec, +} impl MapBuilder for SimpleMapBuilder { - fn build(rng: &mut RandomNumberGenerator, new_depth: i32) -> (Map, Position) { - let mut map = Map::new(new_depth); - let player_pos = SimpleMapBuilder::rooms_and_corridors(rng, &mut map); + fn get_map(&mut self) -> Map { + return self.map.clone(); + } - return (map, player_pos); + fn get_starting_pos(&mut self) -> Position { + return self.starting_position.clone(); + } + + fn build_map(&mut self, rng: &mut RandomNumberGenerator) { + return self.rooms_and_corridors(rng); + } + + fn spawn_entities(&mut self, ecs: &mut World) { + for room in self.rooms.iter().skip(1) { + return spawner::spawn_room(ecs, room, self.depth); + } } } impl SimpleMapBuilder { - fn rooms_and_corridors(rng: &mut RandomNumberGenerator, map: &mut Map) -> Position { + pub fn new(new_depth: i32) -> SimpleMapBuilder { + SimpleMapBuilder { + map: Map::new(new_depth), + starting_position: Position { x: 0, y: 0 }, + depth: new_depth, + rooms: Vec::new(), + } + } + + fn rooms_and_corridors(&mut self, rng: &mut RandomNumberGenerator) { const MAX_ROOMS: i32 = 30; const MIN_SIZE: i32 = 6; const MAX_SIZE: i32 = 10; const MAX_OFFSET: u8 = 32; - for idx in 0..map.red_offset.len() { + for idx in 0..self.map.red_offset.len() { let roll = rng.roll_dice(1, MAX_OFFSET as i32); - map.red_offset[idx] = roll as u8; + self.map.red_offset[idx] = roll as u8; } - for idx in 0..map.green_offset.len() { + for idx in 0..self.map.green_offset.len() { let roll = rng.roll_dice(1, MAX_OFFSET as i32); - map.green_offset[idx] = roll as u8; + self.map.green_offset[idx] = roll as u8; } - for idx in 0..map.blue_offset.len() { + for idx in 0..self.map.blue_offset.len() { let roll = rng.roll_dice(1, MAX_OFFSET as i32); - map.blue_offset[idx] = roll as u8; + self.map.blue_offset[idx] = roll as u8; } for _i in 0..MAX_ROOMS { let w = rng.range(MIN_SIZE, MAX_SIZE); let h = rng.range(MIN_SIZE, MAX_SIZE); - let x = rng.roll_dice(1, map.width - w - 1) - 1; - let y = rng.roll_dice(1, map.height - h - 1) - 1; + let x = rng.roll_dice(1, self.map.width - w - 1) - 1; + let y = rng.roll_dice(1, self.map.height - h - 1) - 1; let new_room = Rect::new(x, y, w, h); let mut ok = true; - for other_room in map.rooms.iter() { + for other_room in self.rooms.iter() { if new_room.intersect(other_room) { ok = false } } if ok { - apply_room_to_map(map, &new_room); + apply_room_to_map(&mut self.map, &new_room); - if !map.rooms.is_empty() { + if !self.rooms.is_empty() { let (new_x, new_y) = new_room.centre(); - let (prev_x, prev_y) = map.rooms[map.rooms.len() - 1].centre(); + let (prev_x, prev_y) = self.rooms[self.rooms.len() - 1].centre(); if rng.range(0, 2) == 1 { - apply_horizontal_tunnel(map, prev_x, new_x, prev_y); - apply_vertical_tunnel(map, prev_y, new_y, new_x); + apply_horizontal_tunnel(&mut self.map, prev_x, new_x, prev_y); + apply_vertical_tunnel(&mut self.map, prev_y, new_y, new_x); } else { - apply_vertical_tunnel(map, prev_y, new_y, prev_x); - apply_horizontal_tunnel(map, prev_x, new_x, new_y); + apply_vertical_tunnel(&mut self.map, prev_y, new_y, prev_x); + apply_horizontal_tunnel(&mut self.map, prev_x, new_x, new_y); } } - map.rooms.push(new_room); + self.rooms.push(new_room); } } - let stairs_position = map.rooms[map.rooms.len() - 1].centre(); - let stairs_idx = map.xy_idx(stairs_position.0, stairs_position.1); - map.tiles[stairs_idx] = TileType::DownStair; + let stairs_position = self.rooms[self.rooms.len() - 1].centre(); + let stairs_idx = self.map.xy_idx(stairs_position.0, stairs_position.1); + self.map.tiles[stairs_idx] = TileType::DownStair; - let start_pos = map.rooms[0].centre(); - return Position { x: start_pos.0, y: start_pos.1 }; + let start_pos = self.rooms[0].centre(); + self.starting_position = Position { x: start_pos.0, y: start_pos.1 }; } }