From fe626c8a337772f681d6cb057c912fe1bb902412 Mon Sep 17 00:00:00 2001 From: Peter Hart Date: Fri, 3 Apr 2020 21:41:49 -0400 Subject: [PATCH] turn based actions and monsters react on sight only --- src/components.rs | 6 ++++++ src/main.rs | 46 ++++++++++++++++++++++++++++------------ src/monster_ai_system.rs | 17 +++++++++------ 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/components.rs b/src/components.rs index a3d594e..43810a7 100644 --- a/src/components.rs +++ b/src/components.rs @@ -27,3 +27,9 @@ pub struct Viewshed { #[derive(Component, Debug)] pub struct Monster {} + + +#[derive(Component, Debug)] +pub struct Name { + pub name : String +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c93d638..40e1539 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use rltk::{Console, GameState, Rltk, VirtualKeyCode, RGB}; +use rltk::{Console, GameState, Point, Rltk, VirtualKeyCode, RGB}; use specs::prelude::*; use std::cmp::{max, min}; mod rect; @@ -15,8 +15,15 @@ pub use monster_ai_system::MonsterAI; #[macro_use] extern crate specs_derive; +#[derive(PartialEq, Copy, Clone)] +pub enum RunState { + Paused, + Running, +} + pub struct State { ecs: World, + runstate: RunState, } pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { @@ -30,16 +37,18 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { if map.tiles[destination_idx] != TileType::Wall { 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 => try_move_player(-1, 0, &mut gs.ecs), VirtualKeyCode::Numpad4 => try_move_player(-1, 0, &mut gs.ecs), @@ -53,9 +62,10 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) { VirtualKeyCode::Down => try_move_player(0, 1, &mut gs.ecs), VirtualKeyCode::Numpad2 => try_move_player(0, 1, &mut gs.ecs), VirtualKeyCode::J => try_move_player(0, 1, &mut gs.ecs), - _ => {} + _ => return RunState::Paused, }, } + RunState::Running } impl State { @@ -71,8 +81,12 @@ impl State { impl GameState for State { fn tick(&mut self, ctx: &mut Rltk) { ctx.cls(); - self.run_systems(); - player_input(self, ctx); + if self.runstate == RunState::Running { + self.run_systems(); + self.runstate = RunState::Paused; + } else { + self.runstate = player_input(self, ctx); + } draw_map(&self.ecs, ctx); let positions = self.ecs.read_storage::(); let renderables = self.ecs.read_storage::(); @@ -126,7 +140,10 @@ fn main() { let context = RltkBuilder::simple80x50() .with_title("Roguelike Tutorial") .build(); - let mut gs = State { ecs: World::new() }; + let mut gs = State { + ecs: World::new(), + runstate: RunState::Running, + }; let map = Map::new_map_rooms_and_corridors(); let (player_x, player_y) = map.rooms[0].center(); @@ -135,6 +152,7 @@ fn main() { gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); gs.ecs .create_entity() @@ -157,17 +175,17 @@ fn main() { let mut rng = rltk::RandomNumberGenerator::new(); - for room in map.rooms.iter().skip(1) { + for (idx, room) in map.rooms.iter().skip(1).enumerate() { let (x, y) = room.center(); - let glyph = match rng.roll_dice(1, 2) { - 1 => rltk::to_cp437('g'), - _ => rltk::to_cp437('o'), + let (glyph, name): (u8, String) = match rng.roll_dice(1, 2) { + 1 => (rltk::to_cp437('g'), "Goblin".to_string()), + _ => (rltk::to_cp437('o'), "Orc".to_string()), }; gs.ecs .create_entity() .with(Position { x, y }) .with(Renderable { - glyph: glyph, + glyph, fg: RGB::named(rltk::RED), bg: RGB::named(rltk::BLACK), }) @@ -177,10 +195,12 @@ fn main() { dirty: true, }) .with(Monster {}) + .with(Name { name: format!("{} #{}", &name, idx) }) .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 index 413ea77..478c23c 100644 --- a/src/monster_ai_system.rs +++ b/src/monster_ai_system.rs @@ -1,21 +1,24 @@ -use super::{Map, Monster, Position, Viewshed}; -use rltk::{console, field_of_view, Point}; +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, Position>, ReadStorage<'a, Monster>, + ReadStorage<'a, Name>, ); - fn run(&mut self, data : Self::SystemData) { - let (viewshed, pos, monster) = data; + fn run(&mut self, data: Self::SystemData) { + let (player_pos, viewshed, monster, name) = data; - for (viewshed, pos, monster) in (&viewshed, &pos, &monster).join() { - console::log("Monster considers their own existence") + for (viewshed, _monster, name) in (&viewshed, &monster, &name).join() { + if viewshed.visible_tiles.contains(&*player_pos) { + console::log(format!("Monster {} shouts insults", name.name)); + } } } }