From 8e80ff36398a685056fc0dc20f1bfec722cff24d Mon Sep 17 00:00:00 2001 From: Alex Page Date: Fri, 28 Jan 2022 03:05:56 -0500 Subject: [PATCH] Implement and use map indexing system --- src/main.rs | 14 +---- src/resources/map.rs | 27 +++++---- src/state.rs | 24 ++++---- src/systems/map_indexing_system.rs | 27 +++++++++ src/systems/mod.rs | 6 +- ...monster_motion.rs => monster_ai_system.rs} | 55 +++++++------------ 6 files changed, 79 insertions(+), 74 deletions(-) create mode 100644 src/systems/map_indexing_system.rs rename src/systems/{monster_motion.rs => monster_ai_system.rs} (62%) diff --git a/src/main.rs b/src/main.rs index fd941c8..2e29d1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,7 +56,7 @@ fn main() -> BError { ecs.register::(); ecs.register::(); - let mut map = Map::new(); + let map = Map::new(); let mut rng = RandomNumberGenerator::new(); for (i, tile) in &mut map.get_tiles().iter().enumerate() { if rng.roll_dice(1, 16) < 2 && *tile == TileType::Floor { @@ -80,16 +80,6 @@ fn main() -> BError { } } - { - let entities = ecs.entities(); - let positions = ecs.read_storage::(); - let monsters = ecs.read_storage::(); - - for (entity, _monster, pos) in (&entities, &monsters, &positions).join() { - map.set_tile_at(Point { x: pos.x, y: pos.y }, TileType::Monster(entity)); - } - } - let player_start_pos = Point { x: 40, y: 22 }; ecs.create_entity() @@ -107,8 +97,6 @@ fn main() -> BError { }) .build(); - map.set_tile_at(player_start_pos, TileType::Player); - ecs.insert(map); ecs.insert(Point::new(player_start_pos.x, player_start_pos.y)); diff --git a/src/resources/map.rs b/src/resources/map.rs index 87045de..5ac0194 100644 --- a/src/resources/map.rs +++ b/src/resources/map.rs @@ -7,8 +7,6 @@ use specs::Entity; #[derive(PartialEq, Copy, Clone)] pub enum TileType { - Player, - Monster(Entity), Wall, BreakableWall, Floor, @@ -16,6 +14,7 @@ pub enum TileType { pub struct Map { tiles: Vec, + tile_content: Vec>, border_fg: RGB, border_bg: RGB, } @@ -47,11 +46,26 @@ impl Map { } Self { tiles, + tile_content: vec![None; MAP_SIZE], border_fg: RGB::named(vga::get_by_index(rng.range(8, 15))), border_bg: RGB::named(vga::get_by_index(rng.range(1, 7) as usize)), } } + pub fn clear_all_tile_content(&mut self) { + self.tile_content.iter_mut().for_each(|tile| { + *tile = None; + }); + } + + pub fn get_tile_content(&self, index: usize) -> Option { + self.tile_content[index] + } + + pub fn set_tile_content(&mut self, index: usize, entity: Entity) { + self.tile_content[index] = Some(entity); + } + pub fn get_tiles(&self) -> &Vec { &self.tiles } @@ -75,15 +89,6 @@ impl Map { let (x, y) = (point.x as usize, point.y as usize); match tile { - TileType::Player | TileType::Monster(_) => { - ctx.set( - x + MAP_X, - y + MAP_Y, - RGB::named(vga::BLACK), - RGB::named(vga::BLACK), - to_cp437(' '), - ); - } TileType::Floor => { ctx.set( x + MAP_X, diff --git a/src/state.rs b/src/state.rs index eeea126..afa3d62 100644 --- a/src/state.rs +++ b/src/state.rs @@ -2,9 +2,8 @@ use std::time::{Duration, Instant}; use crate::components::monster::damage_for_kind; use crate::components::{Monster, Player, Position, Renderable}; -use crate::resources::map::TileType; use crate::resources::{Clock, Map, ShowDebugInfo, SoundEffects, SoundOutput, Stats}; -use crate::systems::MonsterMotion; +use crate::systems::{MapIndexingSystem, MonsterAiSystem}; use crate::{constants::*, sidebar}; use bracket_lib::prelude::*; use specs::prelude::*; @@ -91,7 +90,8 @@ impl State { let entities = self.ecs.entities(); let mut positions = self.ecs.write_storage::(); let mut players = self.ecs.write_storage::(); - let mut map = self.ecs.write_resource::(); + let monsters = self.ecs.write_storage::(); + let map = self.ecs.read_resource::(); let mut stats = self.ecs.write_resource::(); let mut sound_system = self.ecs.write_resource::(); @@ -109,18 +109,14 @@ impl State { if map.is_solid(destination) { sound_system.play_sound(sound_effects.blocked.clone()); } else { - if let TileType::Monster(monster) = map.get_tile_at(destination) { - if let Some(monster_component) = - self.ecs.read_component::().get(monster) - { + if let Some(e) = map.get_tile_content(map.point2d_to_index(destination)) { + if let Some(monster) = monsters.get(e) { if stats.gems > 0 { - stats.gems -= damage_for_kind(monster_component.kind); + stats.gems -= damage_for_kind(monster.kind); } - let _ = entities.delete(monster); + let _ = entities.delete(e); } } - map.set_tile_at(Point { x: pos.x, y: pos.y }, TileType::Floor); - map.set_tile_at(destination, TileType::Player); pos.x = destination.x; pos.y = destination.y; @@ -144,8 +140,10 @@ impl State { } fn run_systems(&mut self) { - let mut mm = MonsterMotion {}; - mm.run_now(&self.ecs); + let mut map_indexing_system = MapIndexingSystem {}; + map_indexing_system.run_now(&self.ecs); + let mut monster_ai_system = MonsterAiSystem {}; + monster_ai_system.run_now(&self.ecs); self.ecs.maintain(); self.ecs.write_resource::().try_tick(); } diff --git a/src/systems/map_indexing_system.rs b/src/systems/map_indexing_system.rs new file mode 100644 index 0000000..1339cf9 --- /dev/null +++ b/src/systems/map_indexing_system.rs @@ -0,0 +1,27 @@ +use bracket_lib::prelude::*; +use specs::prelude::*; + +use crate::{components::Position, resources::Map}; + +pub struct MapIndexingSystem {} + +impl<'a> System<'a> for MapIndexingSystem { + type SystemData = ( + WriteExpect<'a, Map>, + ReadStorage<'a, Position>, + Entities<'a>, + ); + + fn run(&mut self, data: Self::SystemData) { + let (mut map, position, entities) = data; + + map.clear_all_tile_content(); + for (entity, position) in (&entities, &position).join() { + let index = map.point2d_to_index(Point { + x: position.x, + y: position.y, + }); + map.set_tile_content(index, entity); + } + } +} diff --git a/src/systems/mod.rs b/src/systems/mod.rs index ba3c0bc..a3880b6 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -1,3 +1,5 @@ -pub mod monster_motion; +pub mod map_indexing_system; +pub mod monster_ai_system; -pub use monster_motion::MonsterMotion; +pub use map_indexing_system::MapIndexingSystem; +pub use monster_ai_system::MonsterAiSystem; diff --git a/src/systems/monster_motion.rs b/src/systems/monster_ai_system.rs similarity index 62% rename from src/systems/monster_motion.rs rename to src/systems/monster_ai_system.rs index 52d2f2f..9b0eeb2 100644 --- a/src/systems/monster_motion.rs +++ b/src/systems/monster_ai_system.rs @@ -1,7 +1,7 @@ use crate::{ components::{ monster::{self, damage_for_kind, ticks_for_kind}, - Monster, Position, Renderable, + Monster, Player, Position, Renderable, }, resources::map::TileType, resources::{Clock, Map, Stats}, @@ -9,19 +9,20 @@ use crate::{ use bracket_lib::{prelude::*, random::RandomNumberGenerator}; use specs::prelude::*; -pub struct MonsterMotion {} +pub struct MonsterAiSystem {} #[allow(clippy::type_complexity)] -impl<'a> System<'a> for MonsterMotion { +impl<'a> System<'a> for MonsterAiSystem { type SystemData = ( Entities<'a>, ReadExpect<'a, Clock>, ReadExpect<'a, Point>, - WriteExpect<'a, Map>, + ReadExpect<'a, Map>, WriteExpect<'a, Stats>, WriteStorage<'a, Monster>, WriteStorage<'a, Position>, WriteStorage<'a, Renderable>, + ReadStorage<'a, Player>, ); fn run( @@ -30,11 +31,12 @@ impl<'a> System<'a> for MonsterMotion { entities, clock, player_pos, - mut map, + map, mut stats, mut monsters, mut positions, mut renderables, + players, ): Self::SystemData, ) { let mut data = (&entities, &mut monsters, &mut positions, &mut renderables) @@ -72,42 +74,25 @@ impl<'a> System<'a> for MonsterMotion { y: position.y + delta_y, }; - //for (entity, monster, position, renderable) in &data {} - - match map.get_tile_at(destination) { - TileType::Player => { + if let Some(e) = map.get_tile_content(map.point2d_to_index(destination)) { + if let Some(_player) = players.get(e) { // TODO: Sound if stats.gems > 0 { stats.gems -= damage_for_kind(monster.kind); } - map.set_tile_at( - Point { - x: position.x, - y: position.y, - }, - TileType::Floor, - ); - let _ = entities.delete(*entity); - continue; - } - TileType::Monster(_) => {} - TileType::Wall => {} - TileType::BreakableWall => { - // TODO: Sound - map.set_tile_at(destination, TileType::Floor); let _ = entities.delete(*entity); } - TileType::Floor => { - map.set_tile_at( - Point { - x: position.x, - y: position.y, - }, - TileType::Floor, - ); - map.set_tile_at(destination, TileType::Monster(*entity)); - position.x = destination.x; - position.y = destination.y; + } else { + match map.get_tile_at(destination) { + TileType::Wall => {} + TileType::BreakableWall => { + // TODO: Sound + let _ = entities.delete(*entity); + } + TileType::Floor => { + position.x = destination.x; + position.y = destination.y; + } } }