InputState.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. //-----------------------------------------------------------------------------
  2. // InputState.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using Microsoft.Xna.Framework;
  8. using Microsoft.Xna.Framework.Input;
  9. using Microsoft.Xna.Framework.Input.Touch;
  10. using System.Collections.Generic;
  11. namespace HoneycombRush
  12. {
  13. /// <summary>
  14. /// Helper for reading input from keyboard, gamepad, and touch input. This class
  15. /// tracks both the current and previous state of the input devices, and implements
  16. /// query methods for high level input actions such as "move up through the menu"
  17. /// or "pause the game".
  18. /// </summary>
  19. public class InputState
  20. {
  21. public enum MouseButton
  22. {
  23. Left,
  24. Middle,
  25. Right
  26. }
  27. public const int MaxInputs = 4;
  28. public readonly KeyboardState[] CurrentKeyboardStates;
  29. public readonly MouseState[] CurrentMouseStates;
  30. public readonly GamePadState[] CurrentGamePadStates;
  31. public readonly KeyboardState[] LastKeyboardStates;
  32. public readonly MouseState[] LastMouseStates;
  33. public readonly GamePadState[] LastGamePadStates;
  34. public readonly bool[] GamePadWasConnected;
  35. public TouchCollection TouchState;
  36. public readonly List<GestureSample> Gestures = new List<GestureSample>();
  37. /// <summary>
  38. /// Constructs a new input state.
  39. /// </summary>
  40. public InputState()
  41. {
  42. CurrentKeyboardStates = new KeyboardState[MaxInputs];
  43. CurrentMouseStates = new MouseState[MaxInputs];
  44. CurrentGamePadStates = new GamePadState[MaxInputs];
  45. LastKeyboardStates = new KeyboardState[MaxInputs];
  46. LastMouseStates = new MouseState[MaxInputs];
  47. LastGamePadStates = new GamePadState[MaxInputs];
  48. GamePadWasConnected = new bool[MaxInputs];
  49. }
  50. /// <summary>
  51. /// Reads the latest state of the keyboard and gamepad.
  52. /// </summary>
  53. public void Update()
  54. {
  55. for (int i = 0; i < MaxInputs; i++)
  56. {
  57. LastKeyboardStates[i] = CurrentKeyboardStates[i];
  58. LastMouseStates[i] = CurrentMouseStates[i];
  59. LastGamePadStates[i] = CurrentGamePadStates[i];
  60. CurrentKeyboardStates[i] = Keyboard.GetState((PlayerIndex)i);
  61. CurrentMouseStates[i] = Mouse.GetState();
  62. CurrentGamePadStates[i] = GamePad.GetState((PlayerIndex)i);
  63. // Keep track of whether a gamepad has ever been
  64. // connected, so we can detect if it is unplugged.
  65. if (CurrentGamePadStates[i].IsConnected)
  66. {
  67. GamePadWasConnected[i] = true;
  68. }
  69. }
  70. TouchState = TouchPanel.GetState();
  71. Gestures.Clear();
  72. while (TouchPanel.IsGestureAvailable)
  73. {
  74. Gestures.Add(TouchPanel.ReadGesture());
  75. }
  76. }
  77. /// <summary>
  78. /// Helper for checking if a key was newly pressed during this update. The
  79. /// controllingPlayer parameter specifies which player to read input for.
  80. /// If this is null, it will accept input from any player. When a keypress
  81. /// is detected, the output playerIndex reports which player pressed it.
  82. /// </summary>
  83. public bool IsNewKeyPress(Keys key, PlayerIndex? controllingPlayer,
  84. out PlayerIndex playerIndex)
  85. {
  86. if (controllingPlayer.HasValue)
  87. {
  88. // Read input from the specified player.
  89. playerIndex = controllingPlayer.Value;
  90. int i = (int)playerIndex;
  91. return (CurrentKeyboardStates[i].IsKeyDown(key) &&
  92. LastKeyboardStates[i].IsKeyUp(key));
  93. }
  94. else
  95. {
  96. // Accept input from any player.
  97. return (IsNewKeyPress(key, PlayerIndex.One, out playerIndex) ||
  98. IsNewKeyPress(key, PlayerIndex.Two, out playerIndex) ||
  99. IsNewKeyPress(key, PlayerIndex.Three, out playerIndex) ||
  100. IsNewKeyPress(key, PlayerIndex.Four, out playerIndex));
  101. }
  102. }
  103. /// <summary>
  104. /// Helper for checking if a key is currently pressed during the update. The
  105. /// controllingPlayer parameter specifies which player to read input for.
  106. /// If this is null, it will accept input from any player. When a pressed key
  107. /// is detected, the output playerIndex reports which player pressed it.
  108. /// </summary>
  109. public bool IsKeyDown(Keys key, PlayerIndex? controllingPlayer,
  110. out PlayerIndex playerIndex)
  111. {
  112. if (controllingPlayer.HasValue)
  113. {
  114. // Read input from the specified player.
  115. playerIndex = controllingPlayer.Value;
  116. int i = (int)playerIndex;
  117. return (CurrentKeyboardStates[i].IsKeyDown(key));
  118. }
  119. else
  120. {
  121. // Accept input from any player.
  122. return (IsKeyDown(key, PlayerIndex.One, out playerIndex) ||
  123. IsKeyDown(key, PlayerIndex.Two, out playerIndex) ||
  124. IsKeyDown(key, PlayerIndex.Three, out playerIndex) ||
  125. IsKeyDown(key, PlayerIndex.Four, out playerIndex));
  126. }
  127. }
  128. /// <summary>
  129. /// Helper for checking if a mouse button was newly pressed during this update. The
  130. /// controllingPlayer parameter specifies which player to read input for.
  131. /// If this is null, it will accept input from any player. When a click
  132. /// is detected, the output playerIndex reports which player pressed it.
  133. /// </summary>
  134. public bool IsNewMouseClick(MouseButton mouseButton , PlayerIndex? controllingPlayer,
  135. out PlayerIndex playerIndex)
  136. {
  137. if (controllingPlayer.HasValue)
  138. {
  139. // Read input from the specified player.
  140. playerIndex = controllingPlayer.Value;
  141. int i = (int)playerIndex;
  142. switch( mouseButton){
  143. case MouseButton.Left:
  144. return (CurrentMouseStates[i].LeftButton == ButtonState.Pressed &&
  145. LastMouseStates[i].LeftButton == ButtonState.Released);
  146. case MouseButton.Right:
  147. return (CurrentMouseStates[i].RightButton == ButtonState.Pressed &&
  148. LastMouseStates[i].RightButton == ButtonState.Released);
  149. case MouseButton.Middle:
  150. return (CurrentMouseStates[i].MiddleButton == ButtonState.Pressed &&
  151. LastMouseStates[i].MiddleButton == ButtonState.Released);
  152. default:
  153. return IsNewMouseClick(MouseButton.Left, controllingPlayer, out playerIndex) ||
  154. IsNewMouseClick(MouseButton.Middle, controllingPlayer, out playerIndex) ||
  155. IsNewMouseClick(MouseButton.Right, controllingPlayer, out playerIndex);
  156. }
  157. }
  158. else
  159. {
  160. // Accept input from any player.
  161. return (IsNewMouseClick(mouseButton, PlayerIndex.One, out playerIndex) ||
  162. IsNewMouseClick(mouseButton, PlayerIndex.Two, out playerIndex) ||
  163. IsNewMouseClick(mouseButton, PlayerIndex.Three, out playerIndex) ||
  164. IsNewMouseClick(mouseButton, PlayerIndex.Four, out playerIndex));
  165. }
  166. }
  167. /// <summary>
  168. /// Helper for checking if a mouse button is currently pressed during the update. The
  169. /// controllingPlayer parameter specifies which player to read input for.
  170. /// If this is null, it will accept input from any player. When a pressed button
  171. /// is detected, the output playerIndex reports which player pressed it.
  172. /// </summary>
  173. public bool IsMouseDown(MouseButton mouseButton , PlayerIndex? controllingPlayer,
  174. out PlayerIndex playerIndex)
  175. {
  176. if (controllingPlayer.HasValue)
  177. {
  178. // Read input from the specified player.
  179. playerIndex = controllingPlayer.Value;
  180. int i = (int)playerIndex;
  181. switch( mouseButton ) {
  182. case MouseButton.Left:
  183. return CurrentMouseStates[i].LeftButton == ButtonState.Pressed;
  184. case MouseButton.Right:
  185. return CurrentMouseStates[i].RightButton == ButtonState.Pressed;
  186. case MouseButton.Middle:
  187. return CurrentMouseStates[i].MiddleButton == ButtonState.Pressed;
  188. default:
  189. return IsMouseDown(MouseButton.Left, controllingPlayer, out playerIndex) ||
  190. IsMouseDown(MouseButton.Middle, controllingPlayer, out playerIndex) ||
  191. IsMouseDown(MouseButton.Right, controllingPlayer, out playerIndex);
  192. }
  193. }
  194. else
  195. {
  196. // Accept input from any player.
  197. return (IsMouseDown(mouseButton, PlayerIndex.One, out playerIndex) ||
  198. IsMouseDown(mouseButton, PlayerIndex.Two, out playerIndex) ||
  199. IsMouseDown(mouseButton, PlayerIndex.Three, out playerIndex) ||
  200. IsMouseDown(mouseButton, PlayerIndex.Four, out playerIndex));
  201. }
  202. }
  203. /// <summary>
  204. /// Helper for checking if a button was newly pressed during this update.
  205. /// The controllingPlayer parameter specifies which player to read input for.
  206. /// If this is null, it will accept input from any player. When a button press
  207. /// is detected, the output playerIndex reports which player pressed it.
  208. /// </summary>
  209. public bool IsNewButtonPress(Buttons button, PlayerIndex? controllingPlayer,
  210. out PlayerIndex playerIndex)
  211. {
  212. if (controllingPlayer.HasValue)
  213. {
  214. // Read input from the specified player.
  215. playerIndex = controllingPlayer.Value;
  216. int i = (int)playerIndex;
  217. return (CurrentGamePadStates[i].IsButtonDown(button) &&
  218. LastGamePadStates[i].IsButtonUp(button));
  219. }
  220. else
  221. {
  222. // Accept input from any player.
  223. return (IsNewButtonPress(button, PlayerIndex.One, out playerIndex) ||
  224. IsNewButtonPress(button, PlayerIndex.Two, out playerIndex) ||
  225. IsNewButtonPress(button, PlayerIndex.Three, out playerIndex) ||
  226. IsNewButtonPress(button, PlayerIndex.Four, out playerIndex));
  227. }
  228. }
  229. /// <summary>
  230. /// Checks for a "menu select" input action.
  231. /// The controllingPlayer parameter specifies which player to read input for.
  232. /// If this is null, it will accept input from any player. When the action
  233. /// is detected, the output playerIndex reports which player pressed it.
  234. /// </summary>
  235. public bool IsMenuSelect(PlayerIndex? controllingPlayer,
  236. out PlayerIndex playerIndex)
  237. {
  238. return IsNewKeyPress(Keys.Space, controllingPlayer, out playerIndex) ||
  239. IsNewKeyPress(Keys.Enter, controllingPlayer, out playerIndex) ||
  240. IsNewMouseClick(MouseButton.Left, controllingPlayer, out playerIndex) ||
  241. IsNewButtonPress(Buttons.A, controllingPlayer, out playerIndex) ||
  242. IsNewButtonPress(Buttons.Start, controllingPlayer, out playerIndex);
  243. }
  244. /// <summary>
  245. /// Checks for a "menu cancel" input action.
  246. /// The controllingPlayer parameter specifies which player to read input for.
  247. /// If this is null, it will accept input from any player. When the action
  248. /// is detected, the output playerIndex reports which player pressed it.
  249. /// </summary>
  250. public bool IsMenuCancel(PlayerIndex? controllingPlayer,
  251. out PlayerIndex playerIndex)
  252. {
  253. return IsNewKeyPress(Keys.Escape, controllingPlayer, out playerIndex) ||
  254. IsNewButtonPress(Buttons.B, controllingPlayer, out playerIndex) ||
  255. IsNewButtonPress(Buttons.Back, controllingPlayer, out playerIndex);
  256. }
  257. /// <summary>
  258. /// Checks for a "menu up" input action.
  259. /// The controllingPlayer parameter specifies which player to read
  260. /// input for. If this is null, it will accept input from any player.
  261. /// </summary>
  262. public bool IsMenuUp(PlayerIndex? controllingPlayer)
  263. {
  264. PlayerIndex playerIndex;
  265. return IsNewKeyPress(Keys.Up, controllingPlayer, out playerIndex) ||
  266. IsNewKeyPress(Keys.Left, controllingPlayer, out playerIndex) ||
  267. IsNewButtonPress(Buttons.DPadLeft, controllingPlayer, out playerIndex) ||
  268. IsNewButtonPress(Buttons.LeftThumbstickLeft, controllingPlayer, out playerIndex);
  269. }
  270. /// <summary>
  271. /// Checks for a "menu down" input action.
  272. /// The controllingPlayer parameter specifies which player to read
  273. /// input for. If this is null, it will accept input from any player.
  274. /// </summary>
  275. public bool IsMenuDown(PlayerIndex? controllingPlayer)
  276. {
  277. PlayerIndex playerIndex;
  278. return IsNewKeyPress(Keys.Down, controllingPlayer, out playerIndex) ||
  279. IsNewKeyPress(Keys.Right, controllingPlayer, out playerIndex) ||
  280. IsNewButtonPress(Buttons.DPadRight, controllingPlayer, out playerIndex) ||
  281. IsNewButtonPress(Buttons.LeftThumbstickRight, controllingPlayer, out playerIndex);
  282. }
  283. /// <summary>
  284. /// Checks for a "pause the game" input action.
  285. /// The controllingPlayer parameter specifies which player to read
  286. /// input for. If this is null, it will accept input from any player.
  287. /// </summary>
  288. public bool IsPauseGame(PlayerIndex? controllingPlayer)
  289. {
  290. PlayerIndex playerIndex;
  291. return IsNewKeyPress(Keys.Escape, controllingPlayer, out playerIndex) ||
  292. IsNewButtonPress(Buttons.Back, controllingPlayer, out playerIndex) ||
  293. IsNewButtonPress(Buttons.Start, controllingPlayer, out playerIndex);
  294. }
  295. }
  296. }