Start section 5.12 by adding the master dungeon map
This commit is contained in:
parent
dd894452f3
commit
ca79653703
38
src/main.rs
38
src/main.rs
@ -448,6 +448,9 @@ impl State {
|
||||
*player_entity_writer = player_entity;
|
||||
}
|
||||
|
||||
// Replace the world maps
|
||||
self.ecs.insert(map::MasterDungeonMap::new());
|
||||
|
||||
// Build a new map and place the player
|
||||
self.generate_world_map(1);
|
||||
}
|
||||
@ -457,38 +460,8 @@ impl State {
|
||||
self.mapgen_timer = 0.0;
|
||||
self.mapgen_history.clear();
|
||||
|
||||
let mut rng = self.ecs.write_resource::<RandomNumberGenerator>();
|
||||
let mut builder = map_builders::level_builder(new_depth, &mut rng, 80, 50);
|
||||
builder.build_map(&mut rng);
|
||||
|
||||
std::mem::drop(rng);
|
||||
|
||||
self.mapgen_history = builder.get_snapshot_history();
|
||||
|
||||
let player_start;
|
||||
{
|
||||
let mut worldmap_resource = self.ecs.write_resource::<Map>();
|
||||
*worldmap_resource = builder.get_map();
|
||||
player_start = *builder.get_starting_position().as_mut().unwrap();
|
||||
}
|
||||
|
||||
// Spawn bad guys
|
||||
builder.spawn_entities(&mut self.ecs);
|
||||
|
||||
// Place the player and update resources
|
||||
let mut player_position = self.ecs.write_resource::<Point>();
|
||||
*player_position = player_start.into();
|
||||
let mut position_components = self.ecs.write_storage::<Position>();
|
||||
let player_entity = self.ecs.fetch::<Entity>();
|
||||
if let Some(player_pos_comp) = position_components.get_mut(*player_entity) {
|
||||
player_pos_comp.x = player_start.x;
|
||||
player_pos_comp.y = player_start.y;
|
||||
}
|
||||
|
||||
// Mark the player's visibility as dirty
|
||||
let mut viewshed_components = self.ecs.write_storage::<Viewshed>();
|
||||
if let Some(vs) = viewshed_components.get_mut(*player_entity) {
|
||||
vs.dirty = true;
|
||||
if let Some(history) = map::level_transition(&mut self.ecs, new_depth) {
|
||||
self.mapgen_history = history;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -556,6 +529,7 @@ fn main() -> ::rltk::BError {
|
||||
|
||||
raws::load_raws();
|
||||
|
||||
gs.ecs.insert(map::MasterDungeonMap::new());
|
||||
gs.ecs.insert(Map::new(1, 64, 64, "New Map"));
|
||||
gs.ecs.insert(Point::zero());
|
||||
gs.ecs.insert(RandomNumberGenerator::new());
|
||||
|
@ -1,3 +1,4 @@
|
||||
mod dungeon;
|
||||
mod themes;
|
||||
mod tiletype;
|
||||
|
||||
@ -6,6 +7,7 @@ use std::collections::HashSet;
|
||||
use ::rltk::{Algorithm2D, BaseMap, Point, SmallVec};
|
||||
use ::serde::{Deserialize, Serialize};
|
||||
use ::specs::prelude::*;
|
||||
pub use dungeon::*;
|
||||
pub use themes::*;
|
||||
pub use tiletype::{tile_opaque, tile_walkable, TileType};
|
||||
|
||||
|
132
src/map/dungeon.rs
Normal file
132
src/map/dungeon.rs
Normal file
@ -0,0 +1,132 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ::rltk::{Point, RandomNumberGenerator};
|
||||
use ::serde::{Deserialize, Serialize};
|
||||
use ::specs::prelude::*;
|
||||
|
||||
use crate::components::{Position, Viewshed};
|
||||
use crate::map::{Map, TileType};
|
||||
use crate::map_builders::level_builder;
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||
pub struct MasterDungeonMap {
|
||||
maps: HashMap<i32, Map>,
|
||||
}
|
||||
|
||||
impl MasterDungeonMap {
|
||||
pub fn new() -> MasterDungeonMap {
|
||||
MasterDungeonMap {
|
||||
maps: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_map(&mut self, map: &Map) {
|
||||
self.maps.insert(map.depth, map.clone());
|
||||
}
|
||||
|
||||
pub fn get_map(&self, depth: i32) -> Option<Map> {
|
||||
if self.maps.contains_key(&depth) {
|
||||
let mut result = self.maps[&depth].clone();
|
||||
result.tile_content = vec![Vec::new(); (result.width * result.height) as usize];
|
||||
|
||||
Some(result)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn level_transition(ecs: &mut World, new_depth: i32) -> Option<Vec<Map>> {
|
||||
// Obtain the master dungeon map
|
||||
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
||||
|
||||
// Do we already have a map?
|
||||
if dungeon_master.get_map(new_depth).is_some() {
|
||||
std::mem::drop(dungeon_master);
|
||||
transition_to_existing_map(ecs, new_depth);
|
||||
|
||||
None
|
||||
} else {
|
||||
std::mem::drop(dungeon_master);
|
||||
|
||||
Some(transition_to_new_map(ecs, new_depth))
|
||||
}
|
||||
}
|
||||
|
||||
fn transition_to_new_map(ecs: &mut World, new_depth: i32) -> Vec<Map> {
|
||||
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||
let mut builder = level_builder(new_depth, &mut rng, 80, 50);
|
||||
builder.build_map(&mut rng);
|
||||
|
||||
if new_depth > 1 {
|
||||
if let Some(pos) = &builder.build_data.starting_position {
|
||||
let up_idx = builder.build_data.map.xy_idx(pos.x, pos.y);
|
||||
builder.build_data.map.tiles[up_idx] = TileType::UpStairs;
|
||||
}
|
||||
}
|
||||
|
||||
let mapgen_history = builder.build_data.history.clone();
|
||||
let player_start;
|
||||
{
|
||||
let mut worldmap_resource = ecs.write_resource::<Map>();
|
||||
*worldmap_resource = builder.build_data.map.clone();
|
||||
player_start = *builder.build_data.starting_position.as_mut().unwrap();
|
||||
}
|
||||
|
||||
// Spawn bad guys
|
||||
std::mem::drop(rng);
|
||||
builder.spawn_entities(ecs);
|
||||
|
||||
// Place the player and update resources
|
||||
let (player_x, player_y) = (player_start.x, player_start.y);
|
||||
let mut player_position = ecs.write_resource::<Point>();
|
||||
*player_position = player_start.into();
|
||||
|
||||
let mut position_components = ecs.write_storage::<Position>();
|
||||
let player_entity = ecs.fetch::<Entity>();
|
||||
if let Some(player_pos_comp) = position_components.get_mut(*player_entity) {
|
||||
player_pos_comp.x = player_x;
|
||||
player_pos_comp.y = player_y;
|
||||
}
|
||||
|
||||
// Mark the player's visiblity as dirty
|
||||
let mut viewshed_components = ecs.write_storage::<Viewshed>();
|
||||
if let Some(vs) = viewshed_components.get_mut(*player_entity) {
|
||||
vs.dirty = true;
|
||||
}
|
||||
|
||||
// Store the newly minted map
|
||||
let mut dungeon_master = ecs.write_resource::<MasterDungeonMap>();
|
||||
dungeon_master.store_map(&builder.build_data.map);
|
||||
|
||||
mapgen_history
|
||||
}
|
||||
|
||||
fn transition_to_existing_map(ecs: &mut World, new_depth: i32) {
|
||||
let dungeon_master = ecs.write_resource::<MasterDungeonMap>();
|
||||
let map = dungeon_master.get_map(new_depth).unwrap();
|
||||
let mut worldmap_resource = ecs.write_resource::<Map>();
|
||||
let player_entity = ecs.fetch::<Entity>();
|
||||
|
||||
// Find the down stairs and place the player
|
||||
let w = map.width;
|
||||
for (idx, tt) in map.tiles.iter().enumerate() {
|
||||
if *tt == TileType::DownStairs {
|
||||
let mut player_position = ecs.write_resource::<Point>();
|
||||
*player_position = Point::new(idx as i32 % w, idx as i32 / w);
|
||||
let mut position_components = ecs.write_storage::<Position>();
|
||||
if let Some(player_pos_comp) = position_components.get_mut(*player_entity) {
|
||||
player_pos_comp.x = idx as i32 % w;
|
||||
player_pos_comp.y = idx as i32 / w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*worldmap_resource = map;
|
||||
|
||||
// Mark the player's visibility as dirty
|
||||
let mut viewshed_components = ecs.write_storage::<Viewshed>();
|
||||
if let Some(vs) = viewshed_components.get_mut(*player_entity) {
|
||||
vs.dirty = true;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use ::rltk::{FontCharType, RGB};
|
||||
use ::rltk::{to_cp437, FontCharType, RGB};
|
||||
|
||||
use super::{Map, TileType};
|
||||
|
||||
@ -21,8 +21,6 @@ pub fn tile_glyph(idx: usize, map: &Map) -> (FontCharType, RGB, RGB) {
|
||||
}
|
||||
|
||||
fn get_forest_glyph(idx: usize, map: &Map) -> (FontCharType, RGB, RGB) {
|
||||
use rltk::to_cp437;
|
||||
|
||||
let bg = RGB::from_f32(0., 0., 0.);
|
||||
|
||||
let (glyph, fg) = match map.tiles[idx] {
|
||||
@ -34,6 +32,7 @@ fn get_forest_glyph(idx: usize, map: &Map) -> (FontCharType, RGB, RGB) {
|
||||
TileType::DeepWater => (to_cp437('~'), RGB::named(rltk::BLUE)),
|
||||
TileType::Gravel => (to_cp437(';'), RGB::from_f32(0.5, 0.5, 0.5)),
|
||||
TileType::DownStairs => (to_cp437('>'), RGB::from_f32(0., 1.0, 1.0)),
|
||||
TileType::UpStairs => (to_cp437('<'), RGB::from_f32(0., 1.0, 1.0)),
|
||||
_ => (to_cp437('"'), RGB::from_f32(0.0, 0.6, 0.0)),
|
||||
};
|
||||
|
||||
@ -44,20 +43,21 @@ fn get_tile_glyph_default(idx: usize, map: &Map) -> (rltk::FontCharType, RGB, RG
|
||||
let mut bg = RGB::from_f32(0., 0., 0.);
|
||||
|
||||
let (glyph, mut fg) = match map.tiles[idx] {
|
||||
TileType::Floor => (rltk::to_cp437('.'), RGB::from_f32(0., 0.5, 0.5)),
|
||||
TileType::WoodFloor => (rltk::to_cp437('░'), RGB::named(rltk::CHOCOLATE)),
|
||||
TileType::Floor => (to_cp437('.'), RGB::from_f32(0., 0.5, 0.5)),
|
||||
TileType::WoodFloor => (to_cp437('░'), RGB::named(rltk::CHOCOLATE)),
|
||||
TileType::Wall => {
|
||||
let x = idx as i32 % map.width;
|
||||
let y = idx as i32 / map.width;
|
||||
(wall_glyph(&*map, x, y), RGB::from_f32(0., 1.0, 0.))
|
||||
}
|
||||
TileType::DownStairs => (rltk::to_cp437('>'), RGB::from_f32(0., 1.0, 1.0)),
|
||||
TileType::Bridge => (rltk::to_cp437('.'), RGB::named(rltk::CHOCOLATE)),
|
||||
TileType::Road => (rltk::to_cp437('≡'), RGB::named(rltk::GRAY)),
|
||||
TileType::Grass => (rltk::to_cp437('"'), RGB::named(rltk::GREEN)),
|
||||
TileType::ShallowWater => (rltk::to_cp437('~'), RGB::named(rltk::CYAN)),
|
||||
TileType::DeepWater => (rltk::to_cp437('~'), RGB::named(rltk::NAVY_BLUE)),
|
||||
TileType::Gravel => (rltk::to_cp437(';'), RGB::named(rltk::GRAY)),
|
||||
TileType::DownStairs => (to_cp437('>'), RGB::from_f32(0., 1.0, 1.0)),
|
||||
TileType::Bridge => (to_cp437('.'), RGB::named(rltk::CHOCOLATE)),
|
||||
TileType::Road => (to_cp437('≡'), RGB::named(rltk::GRAY)),
|
||||
TileType::Grass => (to_cp437('"'), RGB::named(rltk::GREEN)),
|
||||
TileType::ShallowWater => (to_cp437('~'), RGB::named(rltk::CYAN)),
|
||||
TileType::DeepWater => (to_cp437('~'), RGB::named(rltk::NAVY_BLUE)),
|
||||
TileType::Gravel => (to_cp437(';'), RGB::named(rltk::GRAY)),
|
||||
TileType::UpStairs => (to_cp437('<'), RGB::from_f32(0., 1.0, 1.0)),
|
||||
};
|
||||
|
||||
if map.bloodstains.contains(&idx) {
|
||||
|
@ -12,6 +12,7 @@ pub enum TileType {
|
||||
WoodFloor,
|
||||
Bridge,
|
||||
Gravel,
|
||||
UpStairs,
|
||||
}
|
||||
|
||||
pub fn tile_walkable(tt: TileType) -> bool {
|
||||
@ -25,6 +26,7 @@ pub fn tile_walkable(tt: TileType) -> bool {
|
||||
| TileType::WoodFloor
|
||||
| TileType::Bridge
|
||||
| TileType::Gravel
|
||||
| TileType::UpStairs
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user