From 42dc9a8625ddb5bdaba2d5b16f691074de8cd4d9 Mon Sep 17 00:00:00 2001 From: Alex Bethel Date: Sun, 2 Jan 2022 14:30:37 -0600 Subject: [PATCH] Begin work on player control --- src/components.rs | 16 ++++++++++++++++ src/main.rs | 12 +++++++++--- src/systems.rs | 34 ++++++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/components.rs b/src/components.rs index bdcbdf0..3d04feb 100644 --- a/src/components.rs +++ b/src/components.rs @@ -16,8 +16,24 @@ pub struct CharRender { pub glyph: char, } +/// Entities that the user can control using the keyboard. +#[derive(Component)] +pub struct Player; + +/// Entities that take turns periodically. +#[derive(Component)] +pub struct TurnTaker { + /// Amount of time from now until the next scheduled turn. + pub next: u32, + + /// Amount of time between turns. + pub maximum: u32, +} + /// Registers every existing component with the given ECS world. pub fn register_all(world: &mut World) { world.register::(); world.register::(); + world.register::(); + world.register::(); } diff --git a/src/main.rs b/src/main.rs index 249aa2f..7cf710e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ -use components::{register_all, CharRender, Position}; +use components::{register_all, CharRender, Player, Position, TurnTaker}; use game::{BranchConfig, DungeonLevel}; use specs::prelude::*; -use systems::IOSystem; +use systems::{IOSystem, TurnTickSystem}; mod components; mod game; @@ -24,10 +24,16 @@ fn main() { .create_entity() .with(Position { x: 5, y: 6 }) .with(CharRender { glyph: '@' }) + .with(Player) + .with(TurnTaker { + next: 0, + maximum: 10, + }) .build(); let mut dispatcher = DispatcherBuilder::new() - .with(IOSystem::new(), "render_system", &[]) + .with(TurnTickSystem, "turn_tick", &[]) + .with(IOSystem::new(), "render", &["turn_tick"]) .build(); loop { diff --git a/src/systems.rs b/src/systems.rs index 47abb9a..80f004f 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -7,7 +7,7 @@ use pancurses::{endwin, initscr, Window}; use specs::prelude::*; use crate::{ - components::{CharRender, Position}, + components::{CharRender, Player, Position, TurnTaker}, game::DungeonLevel, }; @@ -51,9 +51,13 @@ impl<'a> System<'a> for IOSystem { ReadExpect<'a, DungeonLevel>, ReadStorage<'a, CharRender>, ReadStorage<'a, Position>, + ReadStorage<'a, Player>, + ReadStorage<'a, TurnTaker>, ); - fn run(&mut self, (level, renderables, positions): Self::SystemData) { + fn run(&mut self, (level, renderables, positions, players, turns): Self::SystemData) { + self.window.clear(); + // Draw the base level. level.draw(&self.window); @@ -64,10 +68,28 @@ impl<'a> System<'a> for IOSystem { // Leave the cursor at the lower-left. self.window.mv(0, 0); - self.window.refresh(); - // For now, just get a character to avoid redrawing over and - // over. - self.window.getch(); + // On the player's turn, read input. + for (_player, turn) in (&players, &turns).join() { + if turn.next == 0 { + self.window.refresh(); + self.window.getch(); + } + } + } +} + +/// System for ticking the turn counter on every entity; this system +/// implements the relationship between real-world time and in-game +/// time. +pub struct TurnTickSystem; + +impl<'a> System<'a> for TurnTickSystem { + type SystemData = WriteStorage<'a, TurnTaker>; + + fn run(&mut self, mut turn_takers: Self::SystemData) { + for ent in (&mut turn_takers).join() { + ent.next = ent.next.checked_sub(1).unwrap_or(ent.maximum); + } } }