InputState.cs 15 KB

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