Browse Source

Implement high-level handling for GameEvent values, too

Getty Ritter 4 years ago
parent
commit
455a4e7721
2 changed files with 70 additions and 17 deletions
  1. 4 0
      chapter-07-damage/src/main.rs
  2. 66 17
      chapter-07-damage/src/player.rs

+ 4 - 0
chapter-07-damage/src/main.rs

@@ -71,6 +71,8 @@ impl GameState for State {
                 newrunstate = RunState::AwaitingInput;
             }
         }
+        player::HandleInputEvent.run_now(&self.ecs);
+        player::HandleGameEvent.run_now(&self.ecs);
         *self.ecs.write_resource() = newrunstate;
         damage_system::CleanupDead.run_now(&self.ecs);
 
@@ -92,6 +94,8 @@ fn main() {
     gs.ecs.register::<CombatStats>();
     gs.ecs.register::<WantsToMelee>();
     gs.ecs.register::<SufferDamage>();
+    gs.ecs.register::<InputEvent>();
+    gs.ecs.register::<GameEvent>();
 
     let map: Map = Map::new_map_rooms_and_corridors();
     let (player_x, player_y) = map.rooms[0].center();

+ 66 - 17
chapter-07-damage/src/player.rs

@@ -47,13 +47,62 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
     }
 }
 
+fn clamp<T: PartialOrd>(low: T, high: T, val: T) -> T {
+    if val < low {
+        low
+    } else if val > high {
+        high
+    } else {
+        val
+    }
+}
+
 #[derive(Component)]
-enum GameEvent {
-    MoveTo { destination: usize },
+pub enum GameEvent {
+    MoveTo {
+        destination: usize,
+        tgt_x: i32,
+        tgt_y: i32,
+    },
     Attack { target: Entity },
 }
 
-struct HandleInputEvent;
+pub struct HandleGameEvent;
+
+impl<'a> System<'a> for HandleGameEvent {
+    type SystemData = (
+        Entities<'a>,
+        WriteStorage<'a, GameEvent>,
+        WriteStorage<'a, WantsToMelee>,
+        WriteStorage<'a, Position>,
+        WriteStorage<'a, Viewshed>,
+        WriteExpect<'a, Point>,
+        ReadExpect<'a, Map>,
+    );
+
+    fn run(&mut self, (entities, mut game_events, mut melee, mut pos, mut viewshed, mut point, map): Self::SystemData) {
+        for (e, event) in (&entities, &game_events).join() {
+            match event {
+                GameEvent::Attack { target } => {
+                    melee.insert(e, WantsToMelee { target: *target })
+                        .expect("Unable to add melee intention for player");
+                }
+                GameEvent::MoveTo { destination, tgt_x, tgt_y } => {
+                    if !map.blocked[*destination] {
+                        viewshed.get_mut(e).expect("Unable to find viewshed").dirty = true;
+                        pos.get_mut(e).expect("Unable to find position").x = *tgt_x;
+                        pos.get_mut(e).expect("Unable to find position").y = *tgt_y;
+                        point.x = clamp(0, 79, *tgt_x);
+                        point.y = clamp(0, 49, *tgt_y);
+                    }
+                }
+            }
+        }
+        game_events.clear();
+    }
+}
+
+pub struct HandleInputEvent;
 
 impl<'a> System<'a> for HandleInputEvent {
     type SystemData = (
@@ -66,20 +115,20 @@ impl<'a> System<'a> for HandleInputEvent {
     );
 
     fn run(&mut self, (mut event, map, entities, position, stats, mut game_events): Self::SystemData) {
-        for ev in (&event).join() {
+        for (e, ev, pos) in (&entities, &event, &position).join() {
             match *ev {
                 InputEvent::PlayerMovement { delta_x, delta_y } => {
-                    for (e, pos) in (&entities, &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");
-                        }
+                    // depending on what's in the target cell, we
+                    // either want to attack or move
+                    let tgt_x = pos.x + delta_x;
+                    let tgt_y = pos.y + delta_y;
+                    let destination = map.xy_idx(tgt_x, tgt_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, tgt_x, tgt_y })
+                            .expect("Unable to add GameEvent");
                     }
                 }
             }
@@ -93,7 +142,7 @@ impl<'a> System<'a> for HandleInputEvent {
 /// to us, corresponding directly to the set of actions we have bound
 /// on the keys
 #[derive(Component)]
-enum InputEvent {
+pub enum InputEvent {
     // attempt to move the player some amount in the given direction
     // (delta_x and delta_y should be -1, 0, or 1)
     PlayerMovement {
@@ -136,6 +185,6 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
 
             _ => return RunState::AwaitingInput,
         },
-    };
+    }.expect("Unable to insert player movement");
     RunState::PlayerTurn
 }