Browse Source

Dispatch InputEvents to high-level GameEvents

Getty Ritter 4 years ago
parent
commit
074c9c0a5f
2 changed files with 53 additions and 5 deletions
  1. 13 0
      chapter-07-damage/src/map.rs
  2. 40 5
      chapter-07-damage/src/player.rs

+ 13 - 0
chapter-07-damage/src/map.rs

@@ -132,6 +132,19 @@ impl Map {
 
         map
     }
+
+    pub fn get_attackable<'a>(
+        &self,
+        target: usize,
+        stats: &ReadStorage<'a, crate::components::CombatStats>,
+    ) -> Option<Entity> {
+        for potential in self.tile_content[target].iter() {
+            if stats.contains(*potential) {
+                return Some(*potential)
+            }
+        }
+        None
+    }
 }
 
 impl BaseMap for Map {

+ 40 - 5
chapter-07-damage/src/player.rs

@@ -47,6 +47,46 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
     }
 }
 
+#[derive(Component)]
+enum GameEvent {
+    MoveTo { destination: usize },
+    Attack { target: Entity },
+}
+
+struct HandleInputEvent;
+
+impl<'a> System<'a> for HandleInputEvent {
+    type SystemData = (
+        Write<'a, InputEvent>,
+        ReadExpect<'a, Map>,
+        Entities<'a>,
+        ReadStorage<'a, Player>,
+        ReadStorage<'a, Position>,
+        ReadStorage<'a, CombatStats>,
+        WriteStorage<'a, GameEvent>,
+    );
+
+    fn run(&mut self, (mut event, map, entities, player, position, stats, mut game_events): Self::SystemData) {
+        match *event {
+            InputEvent::PlayerMovement { delta_x, delta_y } => {
+                for (e, _, pos) in (&entities, &player, &position).join() {
+                    // depending on what's in the target cell, we
+                    // either want to attack or move
+                    let destination = map.xy_idx(pos.x + delta_x, pos.y + delta_y);
+                    if let Some(target) = map.get_attackable(destination, &stats) {
+                        game_events.insert(e, GameEvent::Attack { target }).expect("Unable to add GameEvent");
+                    } else {
+                        game_events.insert(e, GameEvent::MoveTo { destination }).expect("Unable to add GameEvent");
+                    }
+                }
+            },
+            InputEvent::NoAction => {}
+        }
+        *event = InputEvent::NoAction;
+    }
+}
+
+
 /// This type represents all the "low-level" actions we have available
 /// to us, corresponding directly to the set of actions we have bound
 /// on the keys
@@ -57,8 +97,6 @@ enum InputEvent {
         delta_x: i32,
         delta_y: i32,
     },
-    // quit the game
-    QuitGame,
     // do not take any action at all
     NoAction,
 }
@@ -100,9 +138,6 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
             VirtualKeyCode::Numpad1 | VirtualKeyCode::B =>
                 gs.ecs.insert(InputEvent::PlayerMovement { delta_x: -1, delta_y: 1 }),
 
-            VirtualKeyCode::Q | VirtualKeyCode::Escape =>
-                gs.ecs.insert(InputEvent::QuitGame),
-
             _ => return RunState::AwaitingInput,
         },
     }