Browse Source

Split following into separate syste,

Getty Ritter 2 years ago
parent
commit
15108ccf80

+ 6 - 0
chapter-07-damage/src/components.rs

@@ -69,3 +69,9 @@ pub enum InputEvent {
     // (delta_x and delta_y should be -1, 0, or 1)
     PlayerMovement { delta_x: i32, delta_y: i32 },
 }
+
+#[derive(Component, Copy, Clone, Debug)]
+pub struct Seek {
+    pub tgt_x: i32,
+    pub tgt_y: i32,
+}

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

@@ -33,6 +33,7 @@ impl State {
         systems::MapIndexingSystem.run_now(&self.ecs);
         systems::VisibilitySystem.run_now(&self.ecs);
         systems::MonsterAI.run_now(&self.ecs);
+        systems::MoveFollow.run_now(&self.ecs);
         systems::MeleeCombatSystem.run_now(&self.ecs);
         systems::DamageSystem.run_now(&self.ecs);
         self.ecs.maintain();
@@ -86,6 +87,7 @@ fn main() {
     gs.ecs.register::<SufferDamage>();
     gs.ecs.register::<InputEvent>();
     gs.ecs.register::<MoveEvent>();
+    gs.ecs.register::<Seek>();
 
     let map: Map = Map::new_map_rooms_and_corridors();
     let (player_x, player_y) = map.rooms[0].center();

+ 47 - 23
chapter-07-damage/src/systems/monster_ai_system.rs

@@ -1,4 +1,4 @@
-use crate::{Map, Monster, Position, RunState, Viewshed, WantsToMelee};
+use crate::{Map, Monster, Position, RunState, Seek, Viewshed, WantsToMelee};
 use rltk::Point;
 use specs::prelude::*;
 
@@ -7,36 +7,35 @@ pub struct MonsterAI;
 impl<'a> System<'a> for MonsterAI {
     #[allow(clippy::type_complexity)]
     type SystemData = (
-        WriteExpect<'a, Map>,
         ReadExpect<'a, Point>,
         ReadExpect<'a, Entity>,
         ReadExpect<'a, RunState>,
         Entities<'a>,
-        WriteStorage<'a, Viewshed>,
+        ReadStorage<'a, Viewshed>,
         ReadStorage<'a, Monster>,
         WriteStorage<'a, Position>,
         WriteStorage<'a, WantsToMelee>,
+        WriteStorage<'a, Seek>,
     );
 
     fn run(&mut self, data: Self::SystemData) {
         let (
-            mut map,
             player_pos,
             player_entity,
             runstate,
             entities,
-            mut viewshed,
+            viewshed,
             monster,
-            mut position,
+            position,
             mut wants_to_melee,
+            mut seek,
         ) = data;
 
         if *runstate != RunState::MonsterTurn {
             return;
         }
 
-        for (entity, mut viewshed, _monster, mut pos) in
-            (&entities, &mut viewshed, &monster, &mut position).join()
+        for (entity, viewshed, _monster, pos) in (&entities, &viewshed, &monster, &position).join()
         {
             let distance =
                 rltk::DistanceAlg::Pythagoras.distance2d(Point::new(pos.x, pos.y), *player_pos);
@@ -50,22 +49,47 @@ impl<'a> System<'a> for MonsterAI {
                     )
                     .expect("Unable to insert attack");
             } else if viewshed.visible_tiles.contains(&*player_pos) {
-                // Path to the player
-                let path = rltk::a_star_search(
-                    map.xy_idx(pos.x, pos.y) as i32,
-                    map.xy_idx(player_pos.x, player_pos.y) as i32,
-                    &mut *map,
-                );
-                if path.success && path.steps.len() > 1 {
-                    let mut idx = map.xy_idx(pos.x, pos.y);
-                    map.blocked[idx] = false;
-                    pos.x = path.steps[1] % map.width;
-                    pos.y = path.steps[1] / map.width;
-                    idx = map.xy_idx(pos.x, pos.y);
-                    map.blocked[idx] = true;
-                    viewshed.dirty = true;
-                }
+                seek.insert(
+                    entity,
+                    Seek {
+                        tgt_x: player_pos.x,
+                        tgt_y: player_pos.y,
+                    },
+                )
+                .expect("Unable to insert seek");
             }
         }
     }
 }
+
+pub struct MoveFollow;
+
+impl<'a> System<'a> for MoveFollow {
+    type SystemData = (
+        WriteExpect<'a, Map>,
+        WriteStorage<'a, Position>,
+        WriteStorage<'a, Seek>,
+        WriteStorage<'a, Viewshed>,
+    );
+
+    fn run(&mut self, (mut map, mut position, mut seek, mut viewshed): Self::SystemData) {
+        for (mut pos, seek, mut view) in (&mut position, &seek, &mut viewshed).join() {
+            let path = rltk::a_star_search(
+                map.xy_idx(pos.x, pos.y) as i32,
+                map.xy_idx(seek.tgt_x, seek.tgt_y) as i32,
+                &mut *map,
+            );
+            if path.success && path.steps.len() > 1 {
+                let mut idx = map.xy_idx(pos.x, pos.y);
+                map.blocked[idx] = false;
+                pos.x = path.steps[1] % map.width;
+                pos.y = path.steps[1] / map.width;
+                idx = map.xy_idx(pos.x, pos.y);
+                map.blocked[idx] = true;
+                view.dirty = true;
+            }
+        }
+
+        seek.clear();
+    }
+}