VirtualThumbsticks.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // VirtualThumbsticks.cs
  4. //
  5. // Microsoft Advanced Technology Group
  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.Touch;
  12. #endregion
  13. namespace HoneycombRush
  14. {
  15. /// <summary>
  16. /// Represents virtual thumbsticks which allow touch input.
  17. /// Users can touch the left half of the screen to place the center
  18. /// of the left thumbstick and the right half for the right thumbstick.
  19. /// Users can then drag away from that center to simulate thumbstick input.
  20. ///
  21. /// This is a static class with static methods to get the thumbstick properties,
  22. /// for consistency with other XNA input
  23. /// classes like TouchPanel, Gamepad, Keyboard, etc.
  24. /// </summary>
  25. public static class VirtualThumbsticks
  26. {
  27. #region Fields
  28. // the distance in screen pixels that represents a thumbstick value of 1f.
  29. private const float maxThumbstickDistance = 60f;
  30. // the current positions of the physical touches
  31. private static Vector2 leftPosition;
  32. private static Vector2 rightPosition;
  33. // the IDs of the touches we are tracking for the thumbsticks
  34. private static int leftId = -1;
  35. private static int rightId = -1;
  36. /// <summary>
  37. /// Gets the center position of the left thumbstick.
  38. /// </summary>
  39. public static Vector2? LeftThumbstickCenter { get; private set; }
  40. /// <summary>
  41. /// Gets the center position of the right thumbstick.
  42. /// </summary>
  43. public static Vector2? RightThumbstickCenter { get; private set; }
  44. #endregion
  45. /// <summary>
  46. /// Gets the value of the left thumbstick.
  47. /// </summary>
  48. public static Vector2 LeftThumbstick
  49. {
  50. get
  51. {
  52. // if there is no left thumbstick center, return a value of (0, 0)
  53. if (!LeftThumbstickCenter.HasValue)
  54. {
  55. return Vector2.Zero;
  56. }
  57. // calculate the scaled vector from the touch position to the center,
  58. // scaled by the maximum thumbstick distance
  59. Vector2 l = (leftPosition - LeftThumbstickCenter.Value) / maxThumbstickDistance;
  60. // if the length is more than 1, normalize the vector
  61. if (l.LengthSquared() > 1f)
  62. {
  63. l.Normalize();
  64. }
  65. return l;
  66. }
  67. }
  68. /// <summary>
  69. /// Gets the value of the right thumbstick.
  70. /// </summary>
  71. public static Vector2 RightThumbstick
  72. {
  73. get
  74. {
  75. // if there is no left thumbstick center, return a value of (0, 0)
  76. if (!RightThumbstickCenter.HasValue)
  77. {
  78. return Vector2.Zero;
  79. }
  80. // calculate the scaled vector from the touch position to the center,
  81. // scaled by the maximum thumbstick distance
  82. Vector2 r = (rightPosition - RightThumbstickCenter.Value) / maxThumbstickDistance;
  83. // if the length is more than 1, normalize the vector
  84. if (r.LengthSquared() > 1f)
  85. {
  86. r.Normalize();
  87. }
  88. return r;
  89. }
  90. }
  91. /// <summary>
  92. /// Updates the virtual thumbsticks based on current touch state. This must be called every frame.
  93. /// </summary>
  94. public static void Update(InputState input)
  95. {
  96. TouchLocation? leftTouch = null;
  97. TouchLocation? rightTouch = null;
  98. TouchCollection touches = input.TouchState;
  99. // Examine all the touches to convert them to virtual dpad positions. Note that the 'touches'
  100. // collection is the set of all touches at this instant, not a sequence of events. The only
  101. // sequential information we have access to is the previous location for of each touch.
  102. foreach (TouchLocation touch in touches)
  103. {
  104. if (touch.Id == leftId)
  105. {
  106. // This is a motion of a left-stick touch that we're already tracking
  107. leftTouch = touch;
  108. continue;
  109. }
  110. if (touch.Id == rightId)
  111. {
  112. // This is a motion of a right-stick touch that we're already tracking
  113. rightTouch = touch;
  114. continue;
  115. }
  116. // We didn't continue an existing thumbstick gesture; see if we can start a new one.
  117. //
  118. // We'll use the previous touch position if possible, to get as close as possible to where
  119. // the gesture actually began.
  120. TouchLocation earliestTouch;
  121. if (!touch.TryGetPreviousLocation(out earliestTouch))
  122. {
  123. earliestTouch = touch;
  124. }
  125. if (leftId == -1)
  126. {
  127. // if we are not currently tracking a left thumbstick and this touch is on the left
  128. // half of the screen, start tracking this touch as our left stick
  129. if (earliestTouch.Position.X < TouchPanel.DisplayWidth / 2)
  130. {
  131. leftTouch = earliestTouch;
  132. continue;
  133. }
  134. }
  135. if (rightId == -1)
  136. {
  137. // if we are not currently tracking a right thumbstick and this touch is on the right
  138. // half of the screen, start tracking this touch as our right stick
  139. if (earliestTouch.Position.X >= TouchPanel.DisplayWidth / 2)
  140. {
  141. rightTouch = earliestTouch;
  142. continue;
  143. }
  144. }
  145. }
  146. // if we have a left touch
  147. if (leftTouch.HasValue)
  148. {
  149. // if we have no center, this position is our center
  150. if (!LeftThumbstickCenter.HasValue)
  151. {
  152. LeftThumbstickCenter = leftTouch.Value.Position;
  153. }
  154. // save the position of the touch
  155. leftPosition = leftTouch.Value.Position;
  156. // save the ID of the touch
  157. leftId = leftTouch.Value.Id;
  158. }
  159. else
  160. {
  161. // otherwise reset our values to not track any touches
  162. // for the left thumbstick
  163. LeftThumbstickCenter = null;
  164. leftId = -1;
  165. }
  166. // if we have a right touch
  167. if (rightTouch.HasValue)
  168. {
  169. // if we have no center, this position is our center
  170. if (!RightThumbstickCenter.HasValue)
  171. {
  172. RightThumbstickCenter = rightTouch.Value.Position;
  173. }
  174. // save the position of the touch
  175. rightPosition = rightTouch.Value.Position;
  176. // save the ID of the touch
  177. rightId = rightTouch.Value.Id;
  178. }
  179. else
  180. {
  181. // otherwise reset our values to not track any touches
  182. // for the right thumbstick
  183. RightThumbstickCenter = null;
  184. rightId = -1;
  185. }
  186. }
  187. }
  188. }