From 8bf63ad876c87030a3c1a7d368c3dc655f233bcb Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Fri, 10 Dec 2021 15:17:51 -0500 Subject: [PATCH] Add ability to load string map in the prefab map builder --- src/map_builders/prefab_builder.rs | 152 +++++++++++------- .../prefab_builder/prefab_levels.rs | 60 +++++++ 2 files changed, 155 insertions(+), 57 deletions(-) diff --git a/src/map_builders/prefab_builder.rs b/src/map_builders/prefab_builder.rs index 149ca8b..d00ee03 100644 --- a/src/map_builders/prefab_builder.rs +++ b/src/map_builders/prefab_builder.rs @@ -9,6 +9,7 @@ use specs::prelude::*; #[allow(dead_code)] pub enum PrefabMode { RexLevel { template: &'static str }, + Constant { level: prefab_levels::PrefabLevel }, } pub struct PrefabBuilder { @@ -62,71 +63,17 @@ impl PrefabBuilder { starting_position: Position { x: 0, y: 0 }, depth: new_depth, history: Vec::new(), - mode: PrefabMode::RexLevel { - template: "../resources/wfc-demo1.xp", + mode: PrefabMode::Constant { + level: prefab_levels::WFC_POPULATED, }, spawns: Vec::new(), } } - #[allow(dead_code)] - fn load_rex_map(&mut self, path: &str) { - let xp_file = rltk::rex::XpFile::from_resource(path).unwrap(); - - for layer in &xp_file.layers { - for y in 0..layer.height { - for x in 0..layer.width { - let cell = layer.get(x, y).unwrap(); - if x < self.map.width as usize && y < self.map.height as usize { - let idx = self.map.xy_idx(x as i32, y as i32); - // We're doing some nasty casting to make it easier to type things like '#' in the match - match (cell.ch as u8) as char { - ' ' => self.map.tiles[idx] = TileType::Floor, // space - '#' => self.map.tiles[idx] = TileType::Wall, // # - '@' => { - self.map.tiles[idx] = TileType::Floor; - self.starting_position = Position { - x: x as i32, - y: y as i32, - }; - } - '>' => self.map.tiles[idx] = TileType::DownStairs, - 'g' => { - self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Goblin".to_string())); - } - 'o' => { - self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Orc".to_string())); - } - '^' => { - self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Bear Trap".to_string())); - } - '%' => { - self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Rations".to_string())); - } - '!' => { - self.map.tiles[idx] = TileType::Floor; - self.spawns.push((idx, "Health Potion".to_string())); - } - _ => { - rltk::console::log(format!( - "Unknown glyph loading map: {}", - (cell.ch as u8) as char - )); - } - } - } - } - } - } - } - fn build(&mut self) { match self.mode { PrefabMode::RexLevel { template } => self.load_rex_map(&template), + PrefabMode::Constant { level } => self.load_ascii_map(&level), } self.take_snapshot(); @@ -157,4 +104,95 @@ impl PrefabBuilder { self.take_snapshot(); } } + + fn char_to_map(&mut self, ch: char, idx: usize) { + match ch { + ' ' => self.map.tiles[idx] = TileType::Floor, + '#' => self.map.tiles[idx] = TileType::Wall, + '@' => { + let x = idx as i32 % self.map.width; + let y = idx as i32 / self.map.width; + self.map.tiles[idx] = TileType::Floor; + self.starting_position = Position { + x: x as i32, + y: y as i32, + }; + } + '>' => self.map.tiles[idx] = TileType::DownStairs, + 'g' => { + self.map.tiles[idx] = TileType::Floor; + self.spawns.push((idx, "Goblin".to_string())); + } + 'o' => { + self.map.tiles[idx] = TileType::Floor; + self.spawns.push((idx, "Orc".to_string())); + } + '^' => { + self.map.tiles[idx] = TileType::Floor; + self.spawns.push((idx, "Bear Trap".to_string())); + } + '%' => { + self.map.tiles[idx] = TileType::Floor; + self.spawns.push((idx, "Rations".to_string())); + } + '!' => { + self.map.tiles[idx] = TileType::Floor; + self.spawns.push((idx, "Health Potion".to_string())); + } + _ => { + rltk::console::log(format!("Unknown glyph loading map: {}", (ch as u8) as char)); + } + } + } + + #[allow(dead_code)] + fn load_rex_map(&mut self, path: &str) { + let xp_file = rltk::rex::XpFile::from_resource(path).unwrap(); + + for layer in &xp_file.layers { + for y in 0..layer.height { + for x in 0..layer.width { + let cell = layer.get(x, y).unwrap(); + if x < self.map.width as usize && y < self.map.height as usize { + let idx = self.map.xy_idx(x as i32, y as i32); + // We're doing some nasty casting to make it easier to type things like '#' in the match + self.char_to_map(cell.ch as u8 as char, idx); + } + } + } + } + } + + fn read_ascii_to_vec(template: &str) -> Vec { + let mut string_vec: Vec = template + .chars() + .filter(|a| *a != '\r' && *a != '\n') + .collect(); + + for c in string_vec.iter_mut() { + if *c as u8 == 160_u8 { + *c = ' '; + } + } + + string_vec + } + + #[allow(dead_code)] + fn load_ascii_map(&mut self, level: &prefab_levels::PrefabLevel) { + // Start by converting to a vector, with newlines removed + let string_vec = Self::read_ascii_to_vec(level.template); + + let mut i = 0; + for ty in 0..level.height { + for tx in 0..level.width { + if tx < self.map.width as usize && ty < self.map.height as usize { + let idx = self.map.xy_idx(tx as i32, ty as i32); + self.char_to_map(string_vec[i], idx); + } + + i += 1; + } + } + } } diff --git a/src/map_builders/prefab_builder/prefab_levels.rs b/src/map_builders/prefab_builder/prefab_levels.rs index e69de29..5b605ea 100644 --- a/src/map_builders/prefab_builder/prefab_levels.rs +++ b/src/map_builders/prefab_builder/prefab_levels.rs @@ -0,0 +1,60 @@ +#[derive(PartialEq, Copy, Clone)] +pub struct PrefabLevel { + pub template: &'static str, + pub width: usize, + pub height: usize, +} + +#[allow(dead_code)] +pub const WFC_POPULATED: PrefabLevel = PrefabLevel { + template: LEVEL_MAP, + width: 80, + height: 43, +}; + +#[allow(dead_code)] +const LEVEL_MAP: &str = " +################################################################################ +# ######################################################## ######### +# @ ###### ######### #### ################### ####### +# #### g # ############### ##### +# #### # # ####### #### ############# ### +##### ######### # # ####### ######### #### ##### ### +##### ######### ###### ####### o ######### #### ## ##### ### +## #### ######### ### ## o ### +##### ######### ### #### ####### ## ##### ### +##### ######### ### #### ####### # ### ## ##### ### +##### ######### ### #### ####### ####### ##### o ### +### ## ### #### ####### ################ ### +### ## ### o ###### ########### # ############ ### +### ## ### ###### ########### ### ### +### % ###### ########### # ### ! ## ### +### ## ### ###### ## ####### ## ### +### ## ### ## ### ##### # ######################## ##### +### ## ### ## ### ##### # # ###################### ##### +#### ## ####### ###### ##### ### #### o ########### ###### ##### +#### ## ####### ###### #### ## #### # ######### ###### ###### +# ## ####### ###### #### ## #### ############ ##### ###### +# g ## ####### ###### #### ## % ########### o o #### # # +# ## ### #### ## #### # ####### ## ## #### g # +####### ####### #### ###### ! ! ### # # +###### ##### #### # ###### ### ###### +##### ##### # ########## ### ###### +##### ! ### ###### # ########## o##o ### # ## +##### ### ####### ## # ###### ### g ## +# ## #### ######## ### o ####### ^########^ #### # ## +# g # ###### ######## ##### ####### ^ ^ #### ###### +# ##g#### ###### ######## ################ ##### ###### +# ## ########## ########## ######## ################# ###### # +##### ######### ########## % ######## ################### ######## ## # +#### ### ######## ########## ######## #################### ########## # # +### ##### ###### ######### ######## ########### ####### # g# # +### ##### ############### ### ########### ####### #### # +### ##### #### ############## ######## g g ########### #### # ^ # +#### ###^#### ############# ######## ##### #### # g# # +##### ###### ### ######## ##### g #### ! ####^^ # +#!%^## ### ## ########## ######## gg g # > # +#!%^ ### ### ############### ######## ##### g #### # g# # +# %^## ^ ### ############### ######## ##### ################## +################################################################################ +";