InputState.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Input;
  3. using Microsoft.Xna.Framework.Input.Touch;
  4. using System;
  5. using System.Collections.Generic;
  6. namespace FuelCell
  7. {
  8. /// <summary>
  9. /// The interface definition for Input
  10. /// </summary>
  11. public interface IInputState
  12. {
  13. /// <summary>
  14. /// Update the input state
  15. /// </summary>
  16. void Update();
  17. /// <summary>
  18. /// Get the state of the left thumbstick for a specific player
  19. /// </summary>
  20. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  21. /// <returns>The <see cref="Vector2"/> directional state of the thumbstick</returns>
  22. Vector2 GetThumbStickLeft(PlayerIndex? controllingPlayer);
  23. /// <summary>
  24. /// Get the state of the left thumbstick for a specific player and output the player index
  25. /// </summary>
  26. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  27. /// <param name="playerIndex">The output of the <see cref="PlayerIndex"/> instance</param>
  28. /// <returns>The <see cref="Vector2"/> directional state of the thumbstick</returns>
  29. Vector2 GetThumbStickLeft(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex);
  30. /// <summary>
  31. /// Get the state of the right thumbstick for a specific player
  32. /// </summary>
  33. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  34. /// <returns>The <see cref="Vector2"/> directional state of the thumbstick</returns>
  35. Vector2 GetThumbStickRight(PlayerIndex? controllingPlayer);
  36. /// <summary>
  37. /// Get the state of the right thumbstick for a specific player and output the player index
  38. /// </summary>
  39. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  40. /// <param name="playerIndex">The output of the <see cref="PlayerIndex"/> instance</param>
  41. /// <returns>The <see cref="Vector2"/> directional state of the thumbstick</returns>
  42. Vector2 GetThumbStickRight(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex);
  43. /// <summary>
  44. /// Get the state of the left trigger for a specific player
  45. /// </summary>
  46. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  47. /// <returns>The <see cref="float"/> state of the trigger</returns>
  48. float GetTriggerLeft(PlayerIndex? controllingPlayer);
  49. /// <summary>
  50. /// Get the state of the left trigger for a specific player and output the player index
  51. /// </summary>
  52. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  53. /// <param name="playerIndex">The output of the <see cref="PlayerIndex"/> instance</param>
  54. /// <returns>The <see cref="float"/> state of the trigger</returns>
  55. float GetTriggerLeft(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex);
  56. /// <summary>
  57. /// Get the state of the right trigger for a specific player
  58. /// </summary>
  59. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  60. /// <returns>The <see cref="float"/> state of the trigger</returns>
  61. float GetTriggerRight(PlayerIndex? controllingPlayer);
  62. /// <summary>
  63. /// Get the state of the right trigger for a specific player and output the player index
  64. /// </summary>
  65. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  66. /// <param name="playerIndex">The output of the <see cref="PlayerIndex"/> instance</param>
  67. /// <returns>The <see cref="float"/> state of the trigger</returns>
  68. float GetTriggerRight(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex);
  69. /// <summary>
  70. /// Get input from the player for movement forward and backwards in the game.
  71. /// </summary>
  72. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  73. /// <returns>Returns a <see cref="Vector3"/> positional update for the player</returns>
  74. Vector3 GetPlayerMove(PlayerIndex? controllingPlayer);
  75. /// <summary>
  76. /// Get input from the player for movement left and right in the game.
  77. /// </summary>
  78. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  79. /// <returns>Returns the new turn ratio for the player.</returns>
  80. float GetPlayerTurn(PlayerIndex? controllingPlayer);
  81. /// <summary>
  82. /// Respond to the player wanting to exit the game.
  83. /// </summary>
  84. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  85. /// <returns>Returns true if the player has requested to exit the game.</returns>
  86. bool PlayerExit(PlayerIndex? controllingPlayer);
  87. /// <summary>
  88. /// Respond to the player wanting to start the game.
  89. /// </summary>
  90. /// <param name="controllingPlayer">The <see cref="PlayerIndex"/> of the player to request data for.</param>
  91. /// <returns>Returns true if the player has requested to start the game.</returns>
  92. bool StartGame(PlayerIndex? controllingPlayer);
  93. }
  94. /// <summary>
  95. /// The current implementation for the InputState based on the IInputState interface
  96. /// </summary>
  97. public class InputState : IInputState
  98. {
  99. private readonly Game _game;
  100. // A constant value to limit the maximum number of gamepads that can be connected at a time,
  101. // `4` is usually sufficient but consoles can support more if you want to.
  102. public const int MaxGamePadInputs = 4;
  103. // The CURRENT state of input, values as they are read from the device.
  104. public KeyboardState CurrentKeyboardState;
  105. public readonly GamePadState[] CurrentGamePadStates;
  106. // The PREVIOUS state of the input, so we can compare if an input was just activated, or recently released.
  107. public KeyboardState LastKeyboardState;
  108. public readonly GamePadState[] LastGamePadStates;
  109. // Which gamepads are connected and active
  110. public readonly bool[] GamePadWasConnected;
  111. // Simple boolean to determine if ANY gamepads are connected.
  112. public bool GamePadsAvailable = false;
  113. // If we are on mobile, what is the state of any touchscreen input
  114. public TouchCollection TouchState;
  115. // If we are on mobile, what gestures have been detected.
  116. public readonly List<GestureSample> Gestures = new List<GestureSample>();
  117. /// <summary>
  118. /// Constructs a new input state.
  119. /// </summary>
  120. public InputState(Game game)
  121. {
  122. if (game == null)
  123. {
  124. throw new ArgumentNullException("game", "Game cannot be null.");
  125. }
  126. _game = game;
  127. CurrentKeyboardState = new KeyboardState();
  128. CurrentGamePadStates = new GamePadState[MaxGamePadInputs];
  129. for (int i = 0; i < MaxGamePadInputs; i++)
  130. {
  131. GamePad.GetCapabilities(i);
  132. }
  133. LastKeyboardState = new KeyboardState();
  134. LastGamePadStates = new GamePadState[MaxGamePadInputs];
  135. GamePadWasConnected = new bool[MaxGamePadInputs];
  136. if (_game.Services.GetService(typeof(IInputState)) != null)
  137. {
  138. throw new ArgumentException("An Input State class is already registered.");
  139. }
  140. // Once the InputState class has been initialized, then register the current instance with the Game Services registry.
  141. _game.Services.AddService(typeof(IInputState), this);
  142. }
  143. /// <summary>
  144. /// Reads the latest state of the keyboard, gamepads and touch.
  145. /// </summary>
  146. public void Update()
  147. {
  148. LastKeyboardState = CurrentKeyboardState;
  149. CurrentKeyboardState = Keyboard.GetState();
  150. GamePadsAvailable = false;
  151. for (int i = 0; i < MaxGamePadInputs; i++)
  152. {
  153. LastGamePadStates[i] = CurrentGamePadStates[i];
  154. CurrentGamePadStates[i] = GamePad.GetState((PlayerIndex)i);
  155. // Keep track of whether a gamepad has ever been
  156. // connected, so we can detect if it is unplugged.
  157. if (CurrentGamePadStates[i].IsConnected)
  158. {
  159. GamePadsAvailable = true;
  160. GamePadWasConnected[i] = true;
  161. }
  162. }
  163. TouchState = TouchPanel.GetState();
  164. Gestures.Clear();
  165. while (TouchPanel.IsGestureAvailable)
  166. {
  167. Gestures.Add(TouchPanel.ReadGesture());
  168. }
  169. }
  170. /// <summary>
  171. /// Helper for checking if a key was pressed during this update.
  172. /// </summary>
  173. private bool IsKeyPressed(Keys key)
  174. {
  175. return CurrentKeyboardState.IsKeyDown(key);
  176. }
  177. /// <summary>
  178. /// Helper for checking if a key was newly pressed during this update.
  179. /// Key is pressed this frame but was not previously pressed.
  180. /// </summary>
  181. private bool IsNewKeyPress(Keys key)
  182. {
  183. return (CurrentKeyboardState.IsKeyDown(key) &&
  184. LastKeyboardState.IsKeyUp(key));
  185. }
  186. /// <summary>
  187. /// Helper for checking if a key was held down during this update,
  188. /// Key is pressed this frame and was already pressed.
  189. /// </summary>
  190. private bool IsKeyHeld(Keys key)
  191. {
  192. return (CurrentKeyboardState.IsKeyDown(key) &&
  193. LastKeyboardState.IsKeyDown(key));
  194. }
  195. /// <summary>
  196. /// Helper for checking if a key was released during this update,
  197. /// Key is not pressed this frame but was previously pressed.
  198. /// </summary>
  199. private bool IsKeyReleased(Keys key)
  200. {
  201. return (CurrentKeyboardState.IsKeyUp(key) &&
  202. LastKeyboardState.IsKeyDown(key));
  203. }
  204. /// <summary>
  205. /// Helper for checking if a button was pressed during this update.
  206. /// The controllingPlayer parameter specifies which player to read input for.
  207. /// If this is null, it will accept input from any player. When a button press
  208. /// is detected, the output playerIndex reports which player pressed it.
  209. /// </summary>
  210. private bool IsButtonPressed(Buttons button, PlayerIndex? controllingPlayer, 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. // This should not happen, but if you request input from a player that is not connected, this will safely return false.
  218. // It could not have been pressed because the player is not connected.
  219. if (i > MaxGamePadInputs)
  220. {
  221. return false;
  222. }
  223. return CurrentGamePadStates[i].IsButtonDown(button);
  224. }
  225. else
  226. {
  227. // Accept input from any player.
  228. return (IsButtonPressed(button, PlayerIndex.One, out playerIndex) ||
  229. IsButtonPressed(button, PlayerIndex.Two, out playerIndex) ||
  230. IsButtonPressed(button, PlayerIndex.Three, out playerIndex) ||
  231. IsButtonPressed(button, PlayerIndex.Four, out playerIndex));
  232. }
  233. }
  234. /// <summary>
  235. /// Helper for checking if a button was newly pressed during this update.
  236. /// The controllingPlayer parameter specifies which player to read input for.
  237. /// If this is null, it will accept input from any player. When a button press
  238. /// is detected, the output playerIndex reports which player pressed it.
  239. /// </summary>
  240. private bool IsNewButtonPress(Buttons button, PlayerIndex? controllingPlayer,
  241. out PlayerIndex playerIndex)
  242. {
  243. if (controllingPlayer.HasValue)
  244. {
  245. // Read input from the specified player.
  246. playerIndex = controllingPlayer.Value;
  247. int i = (int)playerIndex;
  248. if (i > MaxGamePadInputs)
  249. {
  250. return false;
  251. }
  252. return (CurrentGamePadStates[i].IsButtonDown(button) &&
  253. LastGamePadStates[i].IsButtonUp(button));
  254. }
  255. else
  256. {
  257. // Accept input from any player.
  258. return (IsNewButtonPress(button, PlayerIndex.One, out playerIndex) ||
  259. IsNewButtonPress(button, PlayerIndex.Two, out playerIndex) ||
  260. IsNewButtonPress(button, PlayerIndex.Three, out playerIndex) ||
  261. IsNewButtonPress(button, PlayerIndex.Four, out playerIndex));
  262. }
  263. }
  264. /// <summary>
  265. /// Helper for checking if a button was newly pressed during this update.
  266. /// The controllingPlayer parameter specifies which player to read input for.
  267. /// If this is null, it will accept input from any player. When a button press
  268. /// is detected, the output playerIndex reports which player pressed it.
  269. /// </summary>
  270. private bool IsButtonHeld(Buttons button, PlayerIndex? controllingPlayer,
  271. out PlayerIndex playerIndex)
  272. {
  273. if (controllingPlayer.HasValue)
  274. {
  275. // Read input from the specified player.
  276. playerIndex = controllingPlayer.Value;
  277. int i = (int)playerIndex;
  278. if (i > MaxGamePadInputs)
  279. {
  280. return false;
  281. }
  282. return (CurrentGamePadStates[i].IsButtonDown(button) &&
  283. LastGamePadStates[i].IsButtonDown(button));
  284. }
  285. else
  286. {
  287. // Accept input from any player.
  288. return (IsButtonHeld(button, PlayerIndex.One, out playerIndex) ||
  289. IsButtonHeld(button, PlayerIndex.Two, out playerIndex) ||
  290. IsButtonHeld(button, PlayerIndex.Three, out playerIndex) ||
  291. IsButtonHeld(button, PlayerIndex.Four, out playerIndex));
  292. }
  293. }
  294. /// <summary>
  295. /// Helper for checking if a button was newly pressed during this update.
  296. /// The controllingPlayer parameter specifies which player to read input for.
  297. /// If this is null, it will accept input from any player. When a button press
  298. /// is detected, the output playerIndex reports which player pressed it.
  299. /// </summary>
  300. private bool IsButtonReleased(Buttons button, PlayerIndex? controllingPlayer,
  301. out PlayerIndex playerIndex)
  302. {
  303. if (controllingPlayer.HasValue)
  304. {
  305. // Read input from the specified player.
  306. playerIndex = controllingPlayer.Value;
  307. int i = (int)playerIndex;
  308. if (i > MaxGamePadInputs)
  309. {
  310. return false;
  311. }
  312. return (CurrentGamePadStates[i].IsButtonUp(button) &&
  313. LastGamePadStates[i].IsButtonDown(button));
  314. }
  315. else
  316. {
  317. // Accept input from any player.
  318. return (IsButtonReleased(button, PlayerIndex.One, out playerIndex) ||
  319. IsButtonReleased(button, PlayerIndex.Two, out playerIndex) ||
  320. IsButtonReleased(button, PlayerIndex.Three, out playerIndex) ||
  321. IsButtonReleased(button, PlayerIndex.Four, out playerIndex));
  322. }
  323. }
  324. /// <summary>
  325. /// Helper for checking the state of the left thumbstick during this update.
  326. /// The controllingPlayer parameter specifies which player to read input for.
  327. /// If this is null, it will accept input from any player. When a button press
  328. /// is detected, the output playerIndex reports which player pressed it.
  329. /// If no connected gamepad found, it will return Vector2.Zero
  330. /// </summary>
  331. public Vector2 GetThumbStickLeft(PlayerIndex? controllingPlayer)
  332. {
  333. PlayerIndex playerIndex;
  334. return GetThumbStickLeft(controllingPlayer, out playerIndex);
  335. }
  336. /// <summary>
  337. /// Helper for checking the state of the left thumbstick during this update.
  338. /// The controllingPlayer parameter specifies which player to read input for.
  339. /// If this is null, it will accept input from any player. When a button press
  340. /// is detected, the output playerIndex reports which player pressed it.
  341. /// If no connected gamepad found, it will return Vector2.Zero
  342. /// </summary>
  343. public Vector2 GetThumbStickLeft(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
  344. {
  345. if (controllingPlayer.HasValue)
  346. {
  347. // Read input from the specified player.
  348. playerIndex = controllingPlayer.Value;
  349. int i = (int)playerIndex;
  350. return CurrentGamePadStates[i].ThumbSticks.Left;
  351. }
  352. else
  353. {
  354. for (int i = 0; i < MaxGamePadInputs; i++)
  355. {
  356. if (CurrentGamePadStates[i].IsConnected)
  357. {
  358. playerIndex = (PlayerIndex)i;
  359. return CurrentGamePadStates[i].ThumbSticks.Left;
  360. }
  361. }
  362. playerIndex = PlayerIndex.One;
  363. return Vector2.Zero;
  364. }
  365. }
  366. /// <summary>
  367. /// Helper for checking the state of the left thumbstick during this update.
  368. /// The controllingPlayer parameter specifies which player to read input for.
  369. /// If this is null, it will accept input from any player. When a button press
  370. /// is detected, the output playerIndex reports which player pressed it.
  371. /// If no connected gamepad found, it will return Vector2.Zero
  372. /// </summary>
  373. public Vector2 GetThumbStickRight(PlayerIndex? controllingPlayer)
  374. {
  375. PlayerIndex playerIndex;
  376. return GetThumbStickRight(controllingPlayer, out playerIndex);
  377. }
  378. /// <summary>
  379. /// Helper for checking the state of the right thumbstick during this update.
  380. /// The controllingPlayer parameter specifies which player to read input for.
  381. /// If this is null, it will accept input from any player. When a button press
  382. /// is detected, the output playerIndex reports which player pressed it.
  383. /// If no connected gamepad found, it will return Vector2.Zero
  384. /// </summary>
  385. public Vector2 GetThumbStickRight(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
  386. {
  387. if (controllingPlayer.HasValue)
  388. {
  389. // Read input from the specified player.
  390. playerIndex = controllingPlayer.Value;
  391. int i = (int)playerIndex;
  392. return CurrentGamePadStates[i].ThumbSticks.Right;
  393. }
  394. else
  395. {
  396. for (int i = 0; i < MaxGamePadInputs; i++)
  397. {
  398. if (CurrentGamePadStates[i].IsConnected)
  399. {
  400. playerIndex = (PlayerIndex)i;
  401. return CurrentGamePadStates[i].ThumbSticks.Right;
  402. }
  403. }
  404. playerIndex = PlayerIndex.One;
  405. return Vector2.Zero;
  406. }
  407. }
  408. /// <summary>
  409. /// Helper for checking the state of the left trigger during this update.
  410. /// The controllingPlayer parameter specifies which player to read input for.
  411. /// If this is null, it will accept input from any player. When a button press
  412. /// is detected, the output playerIndex reports which player pressed it.
  413. /// If no connected gamepad found, it will return Vector2.Zero
  414. /// </summary>
  415. public float GetTriggerLeft(PlayerIndex? controllingPlayer)
  416. {
  417. PlayerIndex playerIndex;
  418. return GetTriggerLeft(controllingPlayer, out playerIndex);
  419. }
  420. /// <summary>
  421. /// Helper for checking the state of the left trigger during this update.
  422. /// The controllingPlayer parameter specifies which player to read input for.
  423. /// If this is null, it will accept input from any player. When a button press
  424. /// is detected, the output playerIndex reports which player pressed it.
  425. /// If no connected gamepad found, it will return Vector2.Zero
  426. /// </summary>
  427. public float GetTriggerLeft(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
  428. {
  429. if (controllingPlayer.HasValue)
  430. {
  431. // Read input from the specified player.
  432. playerIndex = controllingPlayer.Value;
  433. int i = (int)playerIndex;
  434. return CurrentGamePadStates[i].Triggers.Left;
  435. }
  436. else
  437. {
  438. for (int i = 0; i < MaxGamePadInputs; i++)
  439. {
  440. if (CurrentGamePadStates[i].IsConnected)
  441. {
  442. playerIndex = (PlayerIndex)i;
  443. return CurrentGamePadStates[i].Triggers.Left;
  444. }
  445. }
  446. playerIndex = PlayerIndex.One;
  447. return 0;
  448. }
  449. }
  450. /// <summary>
  451. /// Helper for checking the state of the right trigger during this update.
  452. /// The controllingPlayer parameter specifies which player to read input for.
  453. /// If this is null, it will accept input from any player. When a button press
  454. /// is detected, the output playerIndex reports which player pressed it.
  455. /// If no connected gamepad found, it will return Vector2.Zero
  456. /// </summary>
  457. public float GetTriggerRight(PlayerIndex? controllingPlayer)
  458. {
  459. PlayerIndex playerIndex;
  460. return GetTriggerRight(controllingPlayer, out playerIndex);
  461. }
  462. /// <summary>
  463. /// Helper for checking the state of the right trigger during this update.
  464. /// The controllingPlayer parameter specifies which player to read input for.
  465. /// If this is null, it will accept input from any player. When a button press
  466. /// is detected, the output playerIndex reports which player pressed it.
  467. /// If no connected gamepad found, it will return Vector2.Zero
  468. /// </summary>
  469. public float GetTriggerRight(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
  470. {
  471. if (controllingPlayer.HasValue)
  472. {
  473. // Read input from the specified player.
  474. playerIndex = controllingPlayer.Value;
  475. int i = (int)playerIndex;
  476. return CurrentGamePadStates[i].Triggers.Right;
  477. }
  478. else
  479. {
  480. for (int i = 0; i < MaxGamePadInputs; i++)
  481. {
  482. if (CurrentGamePadStates[i].IsConnected)
  483. {
  484. playerIndex = (PlayerIndex)i;
  485. return CurrentGamePadStates[i].Triggers.Right;
  486. }
  487. }
  488. playerIndex = PlayerIndex.One;
  489. return 0;
  490. }
  491. }
  492. public bool PlayerExit(PlayerIndex? controllingPlayer)
  493. {
  494. return IsNewKeyPress(Keys.Escape) ||
  495. IsNewButtonPress(Buttons.Back, controllingPlayer, out _);
  496. }
  497. public bool StartGame(PlayerIndex? controllingPlayer)
  498. {
  499. return IsNewKeyPress(Keys.Enter) ||
  500. IsNewButtonPress(Buttons.Start, controllingPlayer, out _);
  501. }
  502. public float GetPlayerTurn(PlayerIndex? controllingPlayer)
  503. {
  504. float turnAmount = 0;
  505. Vector2 thumbstickValue = GetThumbStickLeft(controllingPlayer);
  506. if (IsKeyHeld(Keys.A))
  507. {
  508. turnAmount = 1;
  509. }
  510. else if (IsKeyHeld(Keys.D))
  511. {
  512. turnAmount = -1;
  513. }
  514. else if (thumbstickValue.X != 0)
  515. {
  516. turnAmount = -thumbstickValue.X;
  517. }
  518. return turnAmount;
  519. }
  520. public Vector3 GetPlayerMove(PlayerIndex? controllingPlayer)
  521. {
  522. Vector3 movement = Vector3.Zero;
  523. Vector2 thumbstickValue = GetThumbStickLeft(controllingPlayer);
  524. if (IsKeyHeld(Keys.W))
  525. {
  526. movement.Z = 1;
  527. }
  528. else if (IsKeyHeld(Keys.S))
  529. {
  530. movement.Z = -1;
  531. }
  532. else if (thumbstickValue.Y != 0)
  533. {
  534. movement.Z = thumbstickValue.Y;
  535. }
  536. return movement;
  537. }
  538. }
  539. }