2
0

InputState.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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 System;
  11. using System.Collections.Generic;
  12. using Microsoft.Xna.Framework;
  13. using Microsoft.Xna.Framework.Input;
  14. using Microsoft.Xna.Framework.Input.Touch;
  15. #endregion
  16. namespace GameStateManagement
  17. {
  18. /// <summary>
  19. /// Helper for reading input from keyboard, gamepad, and touch input. This class
  20. /// tracks both the current and previous state of the input devices, and implements
  21. /// query methods for high level input actions such as "move up through the menu"
  22. /// or "pause the game".
  23. /// </summary>
  24. public class InputState
  25. {
  26. #region Fields
  27. public const int MaxInputs = 4;
  28. public readonly KeyboardState[] CurrentKeyboardStates;
  29. public readonly GamePadState[] CurrentGamePadStates;
  30. public readonly KeyboardState[] LastKeyboardStates;
  31. public readonly GamePadState[] LastGamePadStates;
  32. public readonly bool[] GamePadWasConnected;
  33. public TouchCollection TouchState;
  34. public MouseState CurrentMouseState;
  35. public MouseState LastMouseState;
  36. public readonly List<GestureSample> Gestures = new List<GestureSample> ();
  37. #endregion
  38. #region Initialization
  39. /// <summary>
  40. /// Constructs a new input state.
  41. /// </summary>
  42. public InputState ()
  43. {
  44. CurrentKeyboardStates = new KeyboardState[MaxInputs];
  45. CurrentGamePadStates = new GamePadState[MaxInputs];
  46. LastKeyboardStates = new KeyboardState[MaxInputs];
  47. LastGamePadStates = new GamePadState[MaxInputs];
  48. GamePadWasConnected = new bool[MaxInputs];
  49. }
  50. #endregion
  51. #region Public Methods
  52. /// <summary>
  53. /// Reads the latest state of the keyboard and gamepad.
  54. /// </summary>
  55. public void Update ()
  56. {
  57. for (int i = 0; i < MaxInputs; i++) {
  58. LastKeyboardStates [i] = CurrentKeyboardStates [i];
  59. LastGamePadStates [i] = CurrentGamePadStates [i];
  60. CurrentKeyboardStates [i] = Keyboard.GetState ((PlayerIndex)i);
  61. CurrentGamePadStates [i] = GamePad.GetState ((PlayerIndex)i);
  62. // Keep track of whether a gamepad has ever been
  63. // connected, so we can detect if it is unplugged.
  64. if (CurrentGamePadStates [i].IsConnected) {
  65. GamePadWasConnected [i] = true;
  66. }
  67. }
  68. TouchState = TouchPanel.GetState ();
  69. LastMouseState = CurrentMouseState;
  70. CurrentMouseState = Mouse.GetState ();
  71. UpdateMouseStates();
  72. Gestures.Clear ();
  73. while (TouchPanel.IsGestureAvailable) {
  74. Gestures.Add (TouchPanel.ReadGesture ());
  75. }
  76. }
  77. bool dragging = false;
  78. bool dragComplete = false;
  79. bool leftMouseDown = false;
  80. int dragThreshold = 3;
  81. MouseGestureType mouseGestureType;
  82. Vector2 currentMousePosition = Vector2.Zero;
  83. Vector2 prevMousePosition = Vector2.Zero;
  84. Vector2 dragMouseStart = Vector2.Zero;
  85. Vector2 dragMouseEnd = Vector2.Zero;
  86. public MouseGestureType MouseGesture
  87. {
  88. get {
  89. return mouseGestureType;
  90. }
  91. }
  92. public Vector2 CurrentMousePosition
  93. {
  94. get {
  95. return currentMousePosition;
  96. }
  97. }
  98. public Vector2 PrevMousePosition
  99. {
  100. get {
  101. return prevMousePosition;
  102. }
  103. }
  104. public Vector2 MouseDelta
  105. {
  106. get {
  107. return prevMousePosition - currentMousePosition;
  108. }
  109. }
  110. public Vector2 MouseDragDelta
  111. {
  112. get {
  113. return dragMouseStart - dragMouseEnd;
  114. }
  115. }
  116. public Vector2 MouseDragStartPosition
  117. {
  118. get {
  119. return dragMouseStart;
  120. }
  121. }
  122. public Vector2 MouseDragEndPosition
  123. {
  124. get {
  125. return dragMouseEnd;
  126. }
  127. }
  128. void UpdateMouseStates ()
  129. {
  130. currentMousePosition.X = CurrentMouseState.X;
  131. currentMousePosition.Y = CurrentMouseState.Y;
  132. prevMousePosition.X = LastMouseState.X;
  133. prevMousePosition.Y = LastMouseState.Y;
  134. if (mouseGestureType.HasFlag(MouseGestureType.LeftClick))
  135. mouseGestureType = mouseGestureType ^ MouseGestureType.LeftClick;
  136. if (mouseGestureType.HasFlag(MouseGestureType.Move))
  137. mouseGestureType = mouseGestureType ^ MouseGestureType.Move;
  138. if (MouseDelta.Length() != 0)
  139. mouseGestureType = mouseGestureType | MouseGestureType.Move;
  140. // If we were dragging and the left mouse button was released
  141. // then we are no longer dragging and need to throw the banana.
  142. if (CurrentMouseState.LeftButton == ButtonState.Released &&
  143. dragging) {
  144. leftMouseDown = false;
  145. dragging = false;
  146. dragComplete = true;
  147. dragMouseEnd = currentMousePosition;
  148. mouseGestureType |= MouseGestureType.DragComplete;
  149. mouseGestureType = mouseGestureType ^ MouseGestureType.FreeDrag;
  150. //Console.WriteLine ("Dragging: " + mouseGestureType);
  151. }
  152. // Let's set the left mouse down and the mouse origin
  153. if (!leftMouseDown && CurrentMouseState.LeftButton == ButtonState.Pressed &&
  154. !CurrentMouseState.Equals (LastMouseState)) {
  155. //Console.WriteLine ("left down");
  156. leftMouseDown = true;
  157. dragComplete = false;
  158. dragMouseStart = currentMousePosition;
  159. }
  160. if (leftMouseDown && CurrentMouseState.LeftButton == ButtonState.Released &&
  161. !CurrentMouseState.Equals (LastMouseState)) {
  162. leftMouseDown = false;
  163. mouseGestureType |= MouseGestureType.LeftClick;
  164. }
  165. // Here we test the distance and if over the threshold then we set the dragging to true
  166. // Current threshold is 5 pixels.
  167. if (leftMouseDown && !dragging) {
  168. Vector2 delta = dragMouseStart - currentMousePosition;
  169. if (delta.Length() > dragThreshold) {
  170. dragging = true;
  171. dragMouseStart = currentMousePosition;
  172. mouseGestureType = mouseGestureType | MouseGestureType.FreeDrag;
  173. //Console.WriteLine ("Dragging: " + mouseGestureType);
  174. }
  175. }
  176. //Console.WriteLine(mouseGestureType);
  177. }
  178. /// <summary>
  179. /// Helper for checking if a key was newly pressed during this update. The
  180. /// controllingPlayer parameter specifies which player to read input for.
  181. /// If this is null, it will accept input from any player. When a keypress
  182. /// is detected, the output playerIndex reports which player pressed it.
  183. /// </summary>
  184. public bool IsNewKeyPress (Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
  185. {
  186. if (controllingPlayer.HasValue) {
  187. // Read input from the specified player.
  188. playerIndex = controllingPlayer.Value;
  189. int i = (int)playerIndex;
  190. return (CurrentKeyboardStates [i].IsKeyDown (key) && LastKeyboardStates [i].IsKeyUp (key));
  191. } else {
  192. // Accept input from any player.
  193. return (IsNewKeyPress (key, PlayerIndex.One, out playerIndex) ||
  194. IsNewKeyPress (key, PlayerIndex.Two, out playerIndex) ||
  195. IsNewKeyPress (key, PlayerIndex.Three, out playerIndex) ||
  196. IsNewKeyPress (key, PlayerIndex.Four, out playerIndex));
  197. }
  198. }
  199. /// <summary>
  200. /// Helper for checking if a button was newly pressed during this update.
  201. /// The controllingPlayer parameter specifies which player to read input for.
  202. /// If this is null, it will accept input from any player. When a button press
  203. /// is detected, the output playerIndex reports which player pressed it.
  204. /// </summary>
  205. public bool IsNewButtonPress (Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
  206. {
  207. if (controllingPlayer.HasValue) {
  208. // Read input from the specified player.
  209. playerIndex = controllingPlayer.Value;
  210. int i = (int)playerIndex;
  211. return (CurrentGamePadStates [i].IsButtonDown (button) && LastGamePadStates [i].IsButtonUp (button));
  212. } else {
  213. // Accept input from any player.
  214. return (IsNewButtonPress (button, PlayerIndex.One, out playerIndex) ||
  215. IsNewButtonPress (button, PlayerIndex.Two, out playerIndex) ||
  216. IsNewButtonPress (button, PlayerIndex.Three, out playerIndex) ||
  217. IsNewButtonPress (button, PlayerIndex.Four, out playerIndex));
  218. }
  219. }
  220. /// <summary>
  221. /// Checks for a "menu select" input action.
  222. /// The controllingPlayer parameter specifies which player to read input for.
  223. /// If this is null, it will accept input from any player. When the action
  224. /// is detected, the output playerIndex reports which player pressed it.
  225. /// </summary>
  226. public bool IsMenuSelect (PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
  227. {
  228. return IsNewKeyPress (Keys.Space, controllingPlayer, out playerIndex) ||
  229. IsNewKeyPress (Keys.Enter, controllingPlayer, out playerIndex) ||
  230. IsNewButtonPress (Buttons.A, controllingPlayer, out playerIndex) ||
  231. IsNewButtonPress (Buttons.Start, controllingPlayer, out playerIndex);
  232. }
  233. /// <summary>
  234. /// Checks for a "menu cancel" input action.
  235. /// The controllingPlayer parameter specifies which player to read input for.
  236. /// If this is null, it will accept input from any player. When the action
  237. /// is detected, the output playerIndex reports which player pressed it.
  238. /// </summary>
  239. public bool IsMenuCancel (PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
  240. {
  241. return IsNewKeyPress (Keys.Escape, controllingPlayer, out playerIndex) ||
  242. IsNewButtonPress (Buttons.B, controllingPlayer, out playerIndex) ||
  243. IsNewButtonPress (Buttons.Back, controllingPlayer, out playerIndex);
  244. }
  245. /// <summary>
  246. /// Checks for a "menu up" input action.
  247. /// The controllingPlayer parameter specifies which player to read
  248. /// input for. If this is null, it will accept input from any player.
  249. /// </summary>
  250. public bool IsMenuUp (PlayerIndex? controllingPlayer)
  251. {
  252. PlayerIndex playerIndex;
  253. return IsNewKeyPress (Keys.Up, controllingPlayer, out playerIndex) ||
  254. IsNewButtonPress (Buttons.DPadUp, controllingPlayer, out playerIndex) ||
  255. IsNewButtonPress (Buttons.LeftThumbstickUp, controllingPlayer, out playerIndex);
  256. }
  257. /// <summary>
  258. /// Checks for a "menu down" 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 IsMenuDown (PlayerIndex? controllingPlayer)
  263. {
  264. PlayerIndex playerIndex;
  265. return IsNewKeyPress (Keys.Down, controllingPlayer, out playerIndex) ||
  266. IsNewButtonPress (Buttons.DPadDown, controllingPlayer, out playerIndex) ||
  267. IsNewButtonPress (Buttons.LeftThumbstickDown, controllingPlayer, out playerIndex);
  268. }
  269. /// <summary>
  270. /// Checks for a "pause the game" input action.
  271. /// The controllingPlayer parameter specifies which player to read
  272. /// input for. If this is null, it will accept input from any player.
  273. /// </summary>
  274. public bool IsPauseGame (PlayerIndex? controllingPlayer)
  275. {
  276. PlayerIndex playerIndex;
  277. return IsNewKeyPress (Keys.Escape, controllingPlayer, out playerIndex) ||
  278. IsNewButtonPress (Buttons.Back, controllingPlayer, out playerIndex) ||
  279. IsNewButtonPress (Buttons.Start, controllingPlayer, out playerIndex);
  280. }
  281. #endregion
  282. }
  283. }