player.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. extern crate rltk;
  2. use rltk::{Point, Rltk, VirtualKeyCode};
  3. extern crate specs;
  4. use super::{CombatStats, Map, Position, RunState, State, Viewshed, WantsToMelee};
  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. #[derive(Component, Copy, Clone)]
  16. pub struct MoveEvent {
  17. destination: usize,
  18. tgt_x: i32,
  19. tgt_y: i32,
  20. }
  21. pub struct HandleMoveEvent;
  22. impl<'a> System<'a> for HandleMoveEvent {
  23. type SystemData = (
  24. WriteStorage<'a, MoveEvent>,
  25. WriteStorage<'a, Position>,
  26. WriteStorage<'a, Viewshed>,
  27. WriteExpect<'a, Point>,
  28. ReadExpect<'a, Map>,
  29. );
  30. fn run(&mut self, (mut move_events, mut pos, mut viewshed, mut point, map): Self::SystemData) {
  31. for (event, pos, viewshed) in (&move_events, &mut pos, &mut viewshed).join() {
  32. let MoveEvent { destination, tgt_x, tgt_y } = *event;
  33. if !map.blocked[destination] {
  34. viewshed.dirty = true;
  35. pos.x = tgt_x;
  36. pos.y = tgt_y;
  37. point.x = clamp(0, 79, tgt_x);
  38. point.y = clamp(0, 49, tgt_y);
  39. }
  40. }
  41. move_events.clear();
  42. }
  43. }
  44. pub struct HandleInputEvent;
  45. impl<'a> System<'a> for HandleInputEvent {
  46. type SystemData = (
  47. WriteStorage<'a, InputEvent>,
  48. ReadExpect<'a, Map>,
  49. Entities<'a>,
  50. ReadStorage<'a, Position>,
  51. ReadStorage<'a, CombatStats>,
  52. WriteStorage<'a, WantsToMelee>,
  53. WriteStorage<'a, MoveEvent>,
  54. );
  55. fn run(&mut self, (mut event, map, entities, position, stats, mut attack, mut mov): Self::SystemData) {
  56. for (e, ev, pos) in (&entities, &event, &position).join() {
  57. match *ev {
  58. InputEvent::PlayerMovement { delta_x, delta_y } => {
  59. // depending on what's in the target cell, we
  60. // either want to attack or move
  61. let tgt_x = pos.x + delta_x;
  62. let tgt_y = pos.y + delta_y;
  63. let destination = map.xy_idx(tgt_x, tgt_y);
  64. if let Some(target) = map.get_attackable(destination, &stats) {
  65. attack.insert(e, WantsToMelee { target })
  66. .expect("Unable to add WantsToAttack");
  67. } else {
  68. mov.insert(e, MoveEvent { destination, tgt_x, tgt_y })
  69. .expect("Unable to add MoveEvent");
  70. }
  71. }
  72. }
  73. }
  74. event.clear();
  75. }
  76. }
  77. /// This type represents all the "low-level" actions we have available
  78. /// to us, corresponding directly to the set of actions we have bound
  79. /// on the keys
  80. #[derive(Component)]
  81. pub enum InputEvent {
  82. // attempt to move the player some amount in the given direction
  83. // (delta_x and delta_y should be -1, 0, or 1)
  84. PlayerMovement {
  85. delta_x: i32,
  86. delta_y: i32,
  87. },
  88. }
  89. pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
  90. let player = *gs.ecs.fetch::<Entity>();
  91. let mut input = gs.ecs.write_storage::<InputEvent>();
  92. // Player movement
  93. match ctx.key {
  94. None => return RunState::AwaitingInput, // Nothing happened
  95. Some(key) => match key {
  96. VirtualKeyCode::Left | VirtualKeyCode::Numpad4 | VirtualKeyCode::H =>
  97. input.insert(player, InputEvent::PlayerMovement { delta_x: -1, delta_y: 0 }),
  98. VirtualKeyCode::Right | VirtualKeyCode::Numpad6 | VirtualKeyCode::L =>
  99. input.insert(player, InputEvent::PlayerMovement { delta_x: 1, delta_y: 0 }),
  100. VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K =>
  101. input.insert(player, InputEvent::PlayerMovement { delta_x: 0, delta_y: -1 }),
  102. VirtualKeyCode::Down | VirtualKeyCode::Numpad2 | VirtualKeyCode::J =>
  103. input.insert(player, InputEvent::PlayerMovement { delta_x: 0, delta_y: 1 }),
  104. // Diagonals
  105. VirtualKeyCode::Numpad9 | VirtualKeyCode::U =>
  106. input.insert(player, InputEvent::PlayerMovement { delta_x: 1, delta_y: -1 }),
  107. VirtualKeyCode::Numpad7 | VirtualKeyCode::Y =>
  108. input.insert(player, InputEvent::PlayerMovement { delta_x: -1, delta_y: -1 }),
  109. VirtualKeyCode::Numpad3 | VirtualKeyCode::N =>
  110. input.insert(player, InputEvent::PlayerMovement { delta_x: 1, delta_y: 1 }),
  111. VirtualKeyCode::Numpad1 | VirtualKeyCode::B =>
  112. input.insert(player, InputEvent::PlayerMovement { delta_x: -1, delta_y: 1 }),
  113. _ => return RunState::AwaitingInput,
  114. },
  115. }.expect("Unable to insert player movement");
  116. RunState::PlayerTurn
  117. }