From 30b0449e99022a68728168fbf8db18b7e2f86544 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Tue, 26 Oct 2021 15:43:59 -0400 Subject: [PATCH] Complete Chapter 2.5 --- src/components.rs | 8 ++++++ src/main.rs | 59 +++++++++++++++++++++++++++++++++++----- src/monster_ai_system.rs | 24 ++++++++++++++++ src/player.rs | 15 +++++++--- 4 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 src/monster_ai_system.rs diff --git a/src/components.rs b/src/components.rs index 4feca6f..9842a96 100644 --- a/src/components.rs +++ b/src/components.rs @@ -24,3 +24,11 @@ pub struct Viewshed { pub range: i32, pub dirty: bool, } + +#[derive(Component)] +pub struct Monster {} + +#[derive(Component)] +pub struct Name { + pub name: String, +} diff --git a/src/main.rs b/src/main.rs index ed20e80..7026337 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use rltk::{GameState, Rltk, RGB}; +use rltk::{GameState, Point, Rltk, RGB}; use specs::prelude::*; mod components; @@ -10,11 +10,20 @@ use player::*; mod rect; mod visibility_system; use visibility_system::VisibilitySystem; +mod monster_ai_system; +use monster_ai_system::*; pub use rect::Rect; +#[derive(PartialEq, Copy, Clone)] +pub enum RunState { + Paused, + Running, +} + pub struct State { - ecs: World, + pub ecs: World, + pub runstate: RunState, } impl State { @@ -22,6 +31,9 @@ impl State { let mut vis = VisibilitySystem {}; vis.run_now(&self.ecs); + let mut mob = MonsterAI {}; + mob.run_now(&self.ecs); + self.ecs.maintain(); } } @@ -30,8 +42,12 @@ impl GameState for State { fn tick(&mut self, ctx: &mut Rltk) { ctx.cls(); - player_input(self, ctx); - self.run_systems(); + if self.runstate == RunState::Running { + self.run_systems(); + self.runstate = RunState::Paused; + } else { + self.runstate = player_input(self, ctx); + } draw_map(&self.ecs, ctx); @@ -55,23 +71,44 @@ fn main() -> rltk::BError { .with_title("Roguelike Tutorial") .build()?; - let mut gs = State { ecs: World::new() }; + let mut gs = State { + ecs: World::new(), + runstate: RunState::Running, + }; gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); + gs.ecs.register::(); let map: Map = Map::new_map_rooms_and_corridors(); let (player_x, player_y) = map.rooms[0].center(); - for room in map.rooms.iter().skip(1) { + let mut rng = rltk::RandomNumberGenerator::new(); + for (i, room) in map.rooms.iter().skip(1).enumerate() { let (x, y) = room.center(); + + let glyph: rltk::FontCharType; + let name: String; + let roll = rng.roll_dice(1, 2); + match roll { + 1 => { + glyph = rltk::to_cp437('g'); + name = "Goblin".to_string(); + } + _ => { + glyph = rltk::to_cp437('o'); + name = "Orc".to_string(); + } + } + gs.ecs .create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437('g'), + glyph, fg: RGB::named(rltk::RED), bg: RGB::named(rltk::BLACK), }) @@ -80,6 +117,10 @@ fn main() -> rltk::BError { range: 8, dirty: true, }) + .with(Monster {}) + .with(Name { + name: format!("{} #{}", &name, i), + }) .build(); } @@ -100,9 +141,13 @@ fn main() -> rltk::BError { range: 8, dirty: true, }) + .with(Name { + name: "Player".to_string(), + }) .build(); gs.ecs.insert(map); + gs.ecs.insert(Point::new(player_x, player_y)); rltk::main_loop(context, gs) } diff --git a/src/monster_ai_system.rs b/src/monster_ai_system.rs new file mode 100644 index 0000000..2491fb7 --- /dev/null +++ b/src/monster_ai_system.rs @@ -0,0 +1,24 @@ +use super::{Monster, Name, Viewshed}; +use rltk::{console, Point}; +use specs::prelude::*; + +pub struct MonsterAI {} + +impl<'a> System<'a> for MonsterAI { + type SystemData = ( + ReadExpect<'a, Point>, + ReadStorage<'a, Viewshed>, + ReadStorage<'a, Monster>, + ReadStorage<'a, Name>, + ); + + fn run(&mut self, data: Self::SystemData) { + let (player_pos, viewshed, monster, name) = data; + + for (viewshed, _monster, name) in (&viewshed, &monster, &name).join() { + if viewshed.visible_tiles.contains(&*player_pos) { + console::log(format!("{} shouts insults", name.name)); + } + } + } +} diff --git a/src/player.rs b/src/player.rs index 9f33f8e..f8ef15a 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,5 +1,6 @@ use super::{Map, Player, Position, State, TileType, Viewshed}; -use rltk::{Rltk, VirtualKeyCode}; +use crate::RunState; +use rltk::{Point, Rltk, VirtualKeyCode}; use specs::prelude::*; use std::cmp::{max, min}; @@ -15,15 +16,19 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { pos.x = min(79, max(0, pos.x + delta_x)); pos.y = min(49, max(0, pos.y + delta_y)); + let mut ppos = ecs.write_resource::(); + ppos.x = pos.x; + ppos.y = pos.y; + viewshed.dirty = true; } } } -pub fn player_input(gs: &mut State, ctx: &mut Rltk) { +pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState { // Player movement match ctx.key { - None => {} // Nothing happened + None => return RunState::Paused, // Nothing happened Some(key) => match key { VirtualKeyCode::Left | VirtualKeyCode::Numpad4 | VirtualKeyCode::H => { try_move_player(-1, 0, &mut gs.ecs) @@ -41,7 +46,9 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) { try_move_player(0, 1, &mut gs.ecs) } - _ => {} + _ => return RunState::Paused, }, } + + RunState::Running }