turn based actions and monsters react on sight only

This commit is contained in:
Peter Hart 2020-04-03 21:41:49 -04:00
parent c454bab2b1
commit fe626c8a33
3 changed files with 49 additions and 20 deletions

View File

@ -27,3 +27,9 @@ pub struct Viewshed {
#[derive(Component, Debug)] #[derive(Component, Debug)]
pub struct Monster {} pub struct Monster {}
#[derive(Component, Debug)]
pub struct Name {
pub name : String
}

View File

@ -1,4 +1,4 @@
use rltk::{Console, GameState, Rltk, VirtualKeyCode, RGB}; use rltk::{Console, GameState, Point, Rltk, VirtualKeyCode, RGB};
use specs::prelude::*; use specs::prelude::*;
use std::cmp::{max, min}; use std::cmp::{max, min};
mod rect; mod rect;
@ -15,8 +15,15 @@ pub use monster_ai_system::MonsterAI;
#[macro_use] #[macro_use]
extern crate specs_derive; extern crate specs_derive;
#[derive(PartialEq, Copy, Clone)]
pub enum RunState {
Paused,
Running,
}
pub struct State { pub struct State {
ecs: World, ecs: World,
runstate: RunState,
} }
pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { 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 { if map.tiles[destination_idx] != TileType::Wall {
pos.x = min(79, max(0, pos.x + delta_x)); pos.x = min(79, max(0, pos.x + delta_x));
pos.y = min(49, max(0, pos.y + delta_y)); pos.y = min(49, max(0, pos.y + delta_y));
let mut ppos = ecs.write_resource::<Point>();
ppos.x = pos.x;
ppos.y = pos.y;
viewshed.dirty = true; 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 // Player movement
match ctx.key { match ctx.key {
None => {} // Nothing happened None => return RunState::Paused, // Nothing happened
Some(key) => match key { Some(key) => match key {
VirtualKeyCode::Left => try_move_player(-1, 0, &mut gs.ecs), VirtualKeyCode::Left => try_move_player(-1, 0, &mut gs.ecs),
VirtualKeyCode::Numpad4 => 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::Down => try_move_player(0, 1, &mut gs.ecs),
VirtualKeyCode::Numpad2 => 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), VirtualKeyCode::J => try_move_player(0, 1, &mut gs.ecs),
_ => {} _ => return RunState::Paused,
}, },
} }
RunState::Running
} }
impl State { impl State {
@ -71,8 +81,12 @@ impl State {
impl GameState for State { impl GameState for State {
fn tick(&mut self, ctx: &mut Rltk) { fn tick(&mut self, ctx: &mut Rltk) {
ctx.cls(); ctx.cls();
self.run_systems(); if self.runstate == RunState::Running {
player_input(self, ctx); self.run_systems();
self.runstate = RunState::Paused;
} else {
self.runstate = player_input(self, ctx);
}
draw_map(&self.ecs, ctx); draw_map(&self.ecs, ctx);
let positions = self.ecs.read_storage::<Position>(); let positions = self.ecs.read_storage::<Position>();
let renderables = self.ecs.read_storage::<Renderable>(); let renderables = self.ecs.read_storage::<Renderable>();
@ -126,7 +140,10 @@ fn main() {
let context = RltkBuilder::simple80x50() let context = RltkBuilder::simple80x50()
.with_title("Roguelike Tutorial") .with_title("Roguelike Tutorial")
.build(); .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 map = Map::new_map_rooms_and_corridors();
let (player_x, player_y) = map.rooms[0].center(); let (player_x, player_y) = map.rooms[0].center();
@ -135,6 +152,7 @@ fn main() {
gs.ecs.register::<Player>(); gs.ecs.register::<Player>();
gs.ecs.register::<Viewshed>(); gs.ecs.register::<Viewshed>();
gs.ecs.register::<Monster>(); gs.ecs.register::<Monster>();
gs.ecs.register::<Name>();
gs.ecs gs.ecs
.create_entity() .create_entity()
@ -157,17 +175,17 @@ fn main() {
let mut rng = rltk::RandomNumberGenerator::new(); 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 (x, y) = room.center();
let glyph = match rng.roll_dice(1, 2) { let (glyph, name): (u8, String) = match rng.roll_dice(1, 2) {
1 => rltk::to_cp437('g'), 1 => (rltk::to_cp437('g'), "Goblin".to_string()),
_ => rltk::to_cp437('o'), _ => (rltk::to_cp437('o'), "Orc".to_string()),
}; };
gs.ecs gs.ecs
.create_entity() .create_entity()
.with(Position { x, y }) .with(Position { x, y })
.with(Renderable { .with(Renderable {
glyph: glyph, glyph,
fg: RGB::named(rltk::RED), fg: RGB::named(rltk::RED),
bg: RGB::named(rltk::BLACK), bg: RGB::named(rltk::BLACK),
}) })
@ -177,10 +195,12 @@ fn main() {
dirty: true, dirty: true,
}) })
.with(Monster {}) .with(Monster {})
.with(Name { name: format!("{} #{}", &name, idx) })
.build(); .build();
} }
gs.ecs.insert(map); gs.ecs.insert(map);
gs.ecs.insert(Point::new(player_x, player_y));
rltk::main_loop(context, gs); rltk::main_loop(context, gs);
} }

View File

@ -1,21 +1,24 @@
use super::{Map, Monster, Position, Viewshed}; use super::{Monster, Name, Viewshed};
use rltk::{console, field_of_view, Point}; use rltk::{console, Point};
use specs::prelude::*; use specs::prelude::*;
pub struct MonsterAI {} pub struct MonsterAI {}
impl<'a> System<'a> for MonsterAI { impl<'a> System<'a> for MonsterAI {
type SystemData = ( type SystemData = (
ReadExpect<'a, Point>,
ReadStorage<'a, Viewshed>, ReadStorage<'a, Viewshed>,
ReadStorage<'a, Position>,
ReadStorage<'a, Monster>, ReadStorage<'a, Monster>,
ReadStorage<'a, Name>,
); );
fn run(&mut self, data : Self::SystemData) { fn run(&mut self, data: Self::SystemData) {
let (viewshed, pos, monster) = data; let (player_pos, viewshed, monster, name) = data;
for (viewshed, pos, monster) in (&viewshed, &pos, &monster).join() { for (viewshed, _monster, name) in (&viewshed, &monster, &name).join() {
console::log("Monster considers their own existence") if viewshed.visible_tiles.contains(&*player_pos) {
console::log(format!("Monster {} shouts insults", name.name));
}
} }
} }
} }