Implement and use map indexing system
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Alex Page 2022-01-28 03:05:56 -05:00
parent 1918f2436a
commit 8e80ff3639
6 changed files with 79 additions and 74 deletions

View file

@ -56,7 +56,7 @@ fn main() -> BError {
ecs.register::<Monster>(); ecs.register::<Monster>();
ecs.register::<Player>(); ecs.register::<Player>();
let mut map = Map::new(); let map = Map::new();
let mut rng = RandomNumberGenerator::new(); let mut rng = RandomNumberGenerator::new();
for (i, tile) in &mut map.get_tiles().iter().enumerate() { for (i, tile) in &mut map.get_tiles().iter().enumerate() {
if rng.roll_dice(1, 16) < 2 && *tile == TileType::Floor { 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::<Position>();
let monsters = ecs.read_storage::<Monster>();
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 }; let player_start_pos = Point { x: 40, y: 22 };
ecs.create_entity() ecs.create_entity()
@ -107,8 +97,6 @@ fn main() -> BError {
}) })
.build(); .build();
map.set_tile_at(player_start_pos, TileType::Player);
ecs.insert(map); ecs.insert(map);
ecs.insert(Point::new(player_start_pos.x, player_start_pos.y)); ecs.insert(Point::new(player_start_pos.x, player_start_pos.y));

View file

@ -7,8 +7,6 @@ use specs::Entity;
#[derive(PartialEq, Copy, Clone)] #[derive(PartialEq, Copy, Clone)]
pub enum TileType { pub enum TileType {
Player,
Monster(Entity),
Wall, Wall,
BreakableWall, BreakableWall,
Floor, Floor,
@ -16,6 +14,7 @@ pub enum TileType {
pub struct Map { pub struct Map {
tiles: Vec<TileType>, tiles: Vec<TileType>,
tile_content: Vec<Option<Entity>>,
border_fg: RGB, border_fg: RGB,
border_bg: RGB, border_bg: RGB,
} }
@ -47,11 +46,26 @@ impl Map {
} }
Self { Self {
tiles, tiles,
tile_content: vec![None; MAP_SIZE],
border_fg: RGB::named(vga::get_by_index(rng.range(8, 15))), 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)), 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<Entity> {
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<TileType> { pub fn get_tiles(&self) -> &Vec<TileType> {
&self.tiles &self.tiles
} }
@ -75,15 +89,6 @@ impl Map {
let (x, y) = (point.x as usize, point.y as usize); let (x, y) = (point.x as usize, point.y as usize);
match tile { 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 => { TileType::Floor => {
ctx.set( ctx.set(
x + MAP_X, x + MAP_X,

View file

@ -2,9 +2,8 @@ use std::time::{Duration, Instant};
use crate::components::monster::damage_for_kind; use crate::components::monster::damage_for_kind;
use crate::components::{Monster, Player, Position, Renderable}; use crate::components::{Monster, Player, Position, Renderable};
use crate::resources::map::TileType;
use crate::resources::{Clock, Map, ShowDebugInfo, SoundEffects, SoundOutput, Stats}; use crate::resources::{Clock, Map, ShowDebugInfo, SoundEffects, SoundOutput, Stats};
use crate::systems::MonsterMotion; use crate::systems::{MapIndexingSystem, MonsterAiSystem};
use crate::{constants::*, sidebar}; use crate::{constants::*, sidebar};
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
@ -91,7 +90,8 @@ impl State {
let entities = self.ecs.entities(); let entities = self.ecs.entities();
let mut positions = self.ecs.write_storage::<Position>(); let mut positions = self.ecs.write_storage::<Position>();
let mut players = self.ecs.write_storage::<Player>(); let mut players = self.ecs.write_storage::<Player>();
let mut map = self.ecs.write_resource::<Map>(); let monsters = self.ecs.write_storage::<Monster>();
let map = self.ecs.read_resource::<Map>();
let mut stats = self.ecs.write_resource::<Stats>(); let mut stats = self.ecs.write_resource::<Stats>();
let mut sound_system = self.ecs.write_resource::<SoundOutput>(); let mut sound_system = self.ecs.write_resource::<SoundOutput>();
@ -109,18 +109,14 @@ impl State {
if map.is_solid(destination) { if map.is_solid(destination) {
sound_system.play_sound(sound_effects.blocked.clone()); sound_system.play_sound(sound_effects.blocked.clone());
} else { } else {
if let TileType::Monster(monster) = map.get_tile_at(destination) { if let Some(e) = map.get_tile_content(map.point2d_to_index(destination)) {
if let Some(monster_component) = if let Some(monster) = monsters.get(e) {
self.ecs.read_component::<Monster>().get(monster)
{
if stats.gems > 0 { 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.x = destination.x;
pos.y = destination.y; pos.y = destination.y;
@ -144,8 +140,10 @@ impl State {
} }
fn run_systems(&mut self) { fn run_systems(&mut self) {
let mut mm = MonsterMotion {}; let mut map_indexing_system = MapIndexingSystem {};
mm.run_now(&self.ecs); 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.maintain();
self.ecs.write_resource::<Clock>().try_tick(); self.ecs.write_resource::<Clock>().try_tick();
} }

View file

@ -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);
}
}
}

View file

@ -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;

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
components::{ components::{
monster::{self, damage_for_kind, ticks_for_kind}, monster::{self, damage_for_kind, ticks_for_kind},
Monster, Position, Renderable, Monster, Player, Position, Renderable,
}, },
resources::map::TileType, resources::map::TileType,
resources::{Clock, Map, Stats}, resources::{Clock, Map, Stats},
@ -9,19 +9,20 @@ use crate::{
use bracket_lib::{prelude::*, random::RandomNumberGenerator}; use bracket_lib::{prelude::*, random::RandomNumberGenerator};
use specs::prelude::*; use specs::prelude::*;
pub struct MonsterMotion {} pub struct MonsterAiSystem {}
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
impl<'a> System<'a> for MonsterMotion { impl<'a> System<'a> for MonsterAiSystem {
type SystemData = ( type SystemData = (
Entities<'a>, Entities<'a>,
ReadExpect<'a, Clock>, ReadExpect<'a, Clock>,
ReadExpect<'a, Point>, ReadExpect<'a, Point>,
WriteExpect<'a, Map>, ReadExpect<'a, Map>,
WriteExpect<'a, Stats>, WriteExpect<'a, Stats>,
WriteStorage<'a, Monster>, WriteStorage<'a, Monster>,
WriteStorage<'a, Position>, WriteStorage<'a, Position>,
WriteStorage<'a, Renderable>, WriteStorage<'a, Renderable>,
ReadStorage<'a, Player>,
); );
fn run( fn run(
@ -30,11 +31,12 @@ impl<'a> System<'a> for MonsterMotion {
entities, entities,
clock, clock,
player_pos, player_pos,
mut map, map,
mut stats, mut stats,
mut monsters, mut monsters,
mut positions, mut positions,
mut renderables, mut renderables,
players,
): Self::SystemData, ): Self::SystemData,
) { ) {
let mut data = (&entities, &mut monsters, &mut positions, &mut renderables) let mut data = (&entities, &mut monsters, &mut positions, &mut renderables)
@ -72,44 +74,27 @@ impl<'a> System<'a> for MonsterMotion {
y: position.y + delta_y, y: position.y + delta_y,
}; };
//for (entity, monster, position, renderable) in &data {} if let Some(e) = map.get_tile_content(map.point2d_to_index(destination)) {
if let Some(_player) = players.get(e) {
match map.get_tile_at(destination) {
TileType::Player => {
// TODO: Sound // TODO: Sound
if stats.gems > 0 { if stats.gems > 0 {
stats.gems -= damage_for_kind(monster.kind); stats.gems -= damage_for_kind(monster.kind);
} }
map.set_tile_at(
Point {
x: position.x,
y: position.y,
},
TileType::Floor,
);
let _ = entities.delete(*entity); let _ = entities.delete(*entity);
continue;
} }
TileType::Monster(_) => {} } else {
match map.get_tile_at(destination) {
TileType::Wall => {} TileType::Wall => {}
TileType::BreakableWall => { TileType::BreakableWall => {
// TODO: Sound // TODO: Sound
map.set_tile_at(destination, TileType::Floor);
let _ = entities.delete(*entity); let _ = entities.delete(*entity);
} }
TileType::Floor => { 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.x = destination.x;
position.y = destination.y; position.y = destination.y;
} }
} }
}
monster.ticks_until_move = ticks_for_kind(monster.kind); monster.ticks_until_move = ticks_for_kind(monster.kind);
} }