player.rs 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. extern crate rltk;
  2. use rltk::{Rltk, VirtualKeyCode};
  3. extern crate specs;
  4. use super::{CombatStats, Map, Position, MoveEvent, RunState, State, WantsToMelee, InputEvent};
  5. use specs::prelude::*;
  6. /// Handles converting low-level `InputEvent` components (which may
  7. /// represent one of several actions, or even a completely invalid
  8. /// action such as walking into a wall) and dispatches them to the
  9. /// relevant high-level intention (e.g. moving in a direction or
  10. /// attacking a target)
  11. pub struct HandleInputEvent;
  12. impl<'a> System<'a> for HandleInputEvent {
  13. type SystemData = (
  14. WriteStorage<'a, InputEvent>,
  15. ReadExpect<'a, Map>,
  16. Entities<'a>,
  17. ReadStorage<'a, Position>,
  18. ReadStorage<'a, CombatStats>,
  19. WriteStorage<'a, WantsToMelee>,
  20. WriteStorage<'a, MoveEvent>,
  21. );
  22. fn run(&mut self, (mut event, map, entities, position, stats, mut attack, mut mov): Self::SystemData) {
  23. for (e, ev, pos) in (&entities, &event, &position).join() {
  24. match *ev {
  25. InputEvent::PlayerMovement { delta_x, delta_y } => {
  26. // depending on what's in the target cell, we
  27. // either want to attack or move
  28. let tgt_x = pos.x + delta_x;
  29. let tgt_y = pos.y + delta_y;
  30. let destination = map.xy_idx(tgt_x, tgt_y);
  31. if let Some(target) = map.get_attackable(destination, &stats) {
  32. attack.insert(e, WantsToMelee { target })
  33. .expect("Unable to add WantsToAttack");
  34. } else {
  35. mov.insert(e, MoveEvent { destination, tgt_x, tgt_y })
  36. .expect("Unable to add MoveEvent");
  37. }
  38. }
  39. }
  40. }
  41. event.clear();
  42. }
  43. }
  44. /// Translates keyboard input into the appropriate `InputEvent` value
  45. pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
  46. let player = *gs.ecs.fetch::<Entity>();
  47. let mut input = gs.ecs.write_storage::<InputEvent>();
  48. // Player movement
  49. match ctx.key {
  50. None => return RunState::AwaitingInput, // Nothing happened
  51. Some(key) => match key {
  52. VirtualKeyCode::Left | VirtualKeyCode::Numpad4 | VirtualKeyCode::H =>
  53. input.insert(player, InputEvent::PlayerMovement { delta_x: -1, delta_y: 0 }),
  54. VirtualKeyCode::Right | VirtualKeyCode::Numpad6 | VirtualKeyCode::L =>
  55. input.insert(player, InputEvent::PlayerMovement { delta_x: 1, delta_y: 0 }),
  56. VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K =>
  57. input.insert(player, InputEvent::PlayerMovement { delta_x: 0, delta_y: -1 }),
  58. VirtualKeyCode::Down | VirtualKeyCode::Numpad2 | VirtualKeyCode::J =>
  59. input.insert(player, InputEvent::PlayerMovement { delta_x: 0, delta_y: 1 }),
  60. // Diagonals
  61. VirtualKeyCode::Numpad9 | VirtualKeyCode::U =>
  62. input.insert(player, InputEvent::PlayerMovement { delta_x: 1, delta_y: -1 }),
  63. VirtualKeyCode::Numpad7 | VirtualKeyCode::Y =>
  64. input.insert(player, InputEvent::PlayerMovement { delta_x: -1, delta_y: -1 }),
  65. VirtualKeyCode::Numpad3 | VirtualKeyCode::N =>
  66. input.insert(player, InputEvent::PlayerMovement { delta_x: 1, delta_y: 1 }),
  67. VirtualKeyCode::Numpad1 | VirtualKeyCode::B =>
  68. input.insert(player, InputEvent::PlayerMovement { delta_x: -1, delta_y: 1 }),
  69. _ => return RunState::AwaitingInput,
  70. },
  71. }.expect("Unable to insert player movement");
  72. RunState::PlayerTurn
  73. }