player.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. extern crate rltk;
  2. use rltk::{Point, Rltk, VirtualKeyCode};
  3. extern crate specs;
  4. use super::{CombatStats, Map, Position, MoveEvent, RunState, State, Viewshed, WantsToMelee, InputEvent};
  5. use specs::prelude::*;
  6. fn clamp<T: PartialOrd>(low: T, high: T, val: T) -> T {
  7. if val < low {
  8. low
  9. } else if val > high {
  10. high
  11. } else {
  12. val
  13. }
  14. }
  15. pub struct HandleMoveEvent;
  16. impl<'a> System<'a> for HandleMoveEvent {
  17. type SystemData = (
  18. WriteStorage<'a, MoveEvent>,
  19. WriteStorage<'a, Position>,
  20. WriteStorage<'a, Viewshed>,
  21. WriteExpect<'a, Point>,
  22. ReadExpect<'a, Map>,
  23. );
  24. fn run(&mut self, (mut move_events, mut pos, mut viewshed, mut point, map): Self::SystemData) {
  25. for (&event, pos, viewshed) in (&move_events, &mut pos, &mut viewshed).join() {
  26. let MoveEvent { destination, tgt_x, tgt_y } = event;
  27. if !map.blocked[destination] {
  28. viewshed.dirty = true;
  29. pos.x = tgt_x;
  30. pos.y = tgt_y;
  31. point.x = clamp(0, 79, tgt_x);
  32. point.y = clamp(0, 49, tgt_y);
  33. }
  34. }
  35. move_events.clear();
  36. }
  37. }
  38. pub struct HandleInputEvent;
  39. impl<'a> System<'a> for HandleInputEvent {
  40. type SystemData = (
  41. WriteStorage<'a, InputEvent>,
  42. ReadExpect<'a, Map>,
  43. Entities<'a>,
  44. ReadStorage<'a, Position>,
  45. ReadStorage<'a, CombatStats>,
  46. WriteStorage<'a, WantsToMelee>,
  47. WriteStorage<'a, MoveEvent>,
  48. );
  49. fn run(&mut self, (mut event, map, entities, position, stats, mut attack, mut mov): Self::SystemData) {
  50. for (e, ev, pos) in (&entities, &event, &position).join() {
  51. match *ev {
  52. InputEvent::PlayerMovement { delta_x, delta_y } => {
  53. // depending on what's in the target cell, we
  54. // either want to attack or move
  55. let tgt_x = pos.x + delta_x;
  56. let tgt_y = pos.y + delta_y;
  57. let destination = map.xy_idx(tgt_x, tgt_y);
  58. if let Some(target) = map.get_attackable(destination, &stats) {
  59. attack.insert(e, WantsToMelee { target })
  60. .expect("Unable to add WantsToAttack");
  61. } else {
  62. mov.insert(e, MoveEvent { destination, tgt_x, tgt_y })
  63. .expect("Unable to add MoveEvent");
  64. }
  65. }
  66. }
  67. }
  68. event.clear();
  69. }
  70. }
  71. pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
  72. let player = *gs.ecs.fetch::<Entity>();
  73. let mut input = gs.ecs.write_storage::<InputEvent>();
  74. // Player movement
  75. match ctx.key {
  76. None => return RunState::AwaitingInput, // Nothing happened
  77. Some(key) => match key {
  78. VirtualKeyCode::Left | VirtualKeyCode::Numpad4 | VirtualKeyCode::H =>
  79. input.insert(player, InputEvent::PlayerMovement { delta_x: -1, delta_y: 0 }),
  80. VirtualKeyCode::Right | VirtualKeyCode::Numpad6 | VirtualKeyCode::L =>
  81. input.insert(player, InputEvent::PlayerMovement { delta_x: 1, delta_y: 0 }),
  82. VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K =>
  83. input.insert(player, InputEvent::PlayerMovement { delta_x: 0, delta_y: -1 }),
  84. VirtualKeyCode::Down | VirtualKeyCode::Numpad2 | VirtualKeyCode::J =>
  85. input.insert(player, InputEvent::PlayerMovement { delta_x: 0, delta_y: 1 }),
  86. // Diagonals
  87. VirtualKeyCode::Numpad9 | VirtualKeyCode::U =>
  88. input.insert(player, InputEvent::PlayerMovement { delta_x: 1, delta_y: -1 }),
  89. VirtualKeyCode::Numpad7 | VirtualKeyCode::Y =>
  90. input.insert(player, InputEvent::PlayerMovement { delta_x: -1, delta_y: -1 }),
  91. VirtualKeyCode::Numpad3 | VirtualKeyCode::N =>
  92. input.insert(player, InputEvent::PlayerMovement { delta_x: 1, delta_y: 1 }),
  93. VirtualKeyCode::Numpad1 | VirtualKeyCode::B =>
  94. input.insert(player, InputEvent::PlayerMovement { delta_x: -1, delta_y: 1 }),
  95. _ => return RunState::AwaitingInput,
  96. },
  97. }.expect("Unable to insert player movement");
  98. RunState::PlayerTurn
  99. }