2
0

Cursor.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // Cursor.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 Microsoft.Xna.Framework;
  12. using Microsoft.Xna.Framework.Graphics;
  13. using Microsoft.Xna.Framework.Input;
  14. using Microsoft.Xna.Framework.Input.Touch;
  15. #endregion
  16. namespace PickingSample
  17. {
  18. /// <summary>
  19. /// Cursor is a DrawableGameComponent that draws a cursor on the screen.
  20. /// </summary>
  21. public class Cursor : DrawableGameComponent
  22. {
  23. #region Fields and Properties
  24. // this constant controls how fast the gamepad moves the cursor. this constant
  25. // is in pixels per second.
  26. const float CursorSpeed = 400.0f;
  27. // this spritebatch is created internally, and is used to draw the cursor.
  28. SpriteBatch spriteBatch;
  29. // this is the sprite that is drawn at the current cursor position.
  30. // textureCenter is used to center the sprite when drawing.
  31. Texture2D cursorTexture;
  32. Vector2 textureCenter;
  33. // Position is the cursor position, and is in screen space.
  34. private Vector2 position;
  35. public Vector2 Position
  36. {
  37. get { return position; }
  38. }
  39. #endregion
  40. #region Initialization
  41. public Cursor(Game game)
  42. : base(game)
  43. {
  44. }
  45. // LoadContent needs to load the cursor texture and find its center.
  46. // also, we need to create a SpriteBatch.
  47. protected override void LoadContent()
  48. {
  49. cursorTexture = Game.Content.Load<Texture2D>("cursor");
  50. textureCenter = new Vector2(cursorTexture.Width / 2, cursorTexture.Height / 2);
  51. spriteBatch = new SpriteBatch(GraphicsDevice);
  52. // we want to default the cursor to start in the center of the screen
  53. Viewport vp = GraphicsDevice.Viewport;
  54. position.X = vp.X + (vp.Width / 2);
  55. position.Y = vp.Y + (vp.Height / 2);
  56. base.LoadContent();
  57. }
  58. #endregion
  59. #region Update
  60. public override void Update(GameTime gameTime)
  61. {
  62. // We use different input on each platform:
  63. // On Xbox, we use the GamePad's DPad and left thumbstick to move the cursor around the screen.
  64. // On Windows, we directly map the cursor to the location of the mouse.
  65. // On Windows Phone, we use the primary touch point for the location of the cursor.
  66. #if XBOX
  67. UpdateXboxInput(gameTime);
  68. #elif WINDOWS
  69. UpdateWindowsInput();
  70. #elif WINDOWS_PHONE
  71. UpdateWindowsPhoneInput();
  72. #endif
  73. }
  74. /// <summary>
  75. /// Handles input for Xbox 360.
  76. /// </summary>
  77. private void UpdateXboxInput(GameTime gameTime)
  78. {
  79. GamePadState currentState = GamePad.GetState(PlayerIndex.One);
  80. // we'll create a vector2, called delta, which will store how much the
  81. // cursor position should change.
  82. Vector2 delta = currentState.ThumbSticks.Left;
  83. // down on the thumbstick is -1. however, in screen coordinates, values
  84. // increase as they go down the screen. so, we have to flip the sign of the
  85. // y component of delta.
  86. delta.Y *= -1;
  87. // check the dpad: if any of its buttons are pressed, that will change delta as well.
  88. if (currentState.DPad.Up == ButtonState.Pressed)
  89. {
  90. delta.Y = -1;
  91. }
  92. if (currentState.DPad.Down == ButtonState.Pressed)
  93. {
  94. delta.Y = 1;
  95. }
  96. if (currentState.DPad.Left == ButtonState.Pressed)
  97. {
  98. delta.X = -1;
  99. }
  100. if (currentState.DPad.Right == ButtonState.Pressed)
  101. {
  102. delta.X = 1;
  103. }
  104. // normalize delta so that we know the cursor can't move faster than CursorSpeed.
  105. if (delta != Vector2.Zero)
  106. {
  107. delta.Normalize();
  108. }
  109. // modify position using delta, the CursorSpeed constant defined above, and
  110. // the elapsed game time.
  111. position += delta * CursorSpeed *
  112. (float)gameTime.ElapsedGameTime.TotalSeconds;
  113. // clamp the cursor position to the viewport, so that it can't move off the screen.
  114. Viewport vp = GraphicsDevice.Viewport;
  115. position.X = MathHelper.Clamp(position.X, vp.X, vp.X + vp.Width);
  116. position.Y = MathHelper.Clamp(position.Y, vp.Y, vp.Y + vp.Height);
  117. }
  118. /// <summary>
  119. /// Handles input for Windows.
  120. /// </summary>
  121. private void UpdateWindowsInput()
  122. {
  123. MouseState mouseState = Mouse.GetState();
  124. position.X = mouseState.X;
  125. position.Y = mouseState.Y;
  126. }
  127. /// <summary>
  128. /// Handles input for Windows Phone.
  129. /// </summary>
  130. private void UpdateWindowsPhoneInput()
  131. {
  132. TouchCollection touches = TouchPanel.GetState();
  133. if (touches.Count > 0)
  134. {
  135. position = touches[0].Position;
  136. }
  137. }
  138. #endregion
  139. #region Draw
  140. public override void Draw(GameTime gameTime)
  141. {
  142. spriteBatch.Begin();
  143. // use textureCenter as the origin of the sprite, so that the cursor is
  144. // drawn centered around Position.
  145. spriteBatch.Draw(cursorTexture, Position, null, Color.White, 0.0f,
  146. textureCenter, 1.0f, SpriteEffects.None, 0.0f);
  147. spriteBatch.End();
  148. }
  149. #endregion
  150. #region CalculateCursorRay
  151. // CalculateCursorRay Calculates a world space ray starting at the camera's
  152. // "eye" and pointing in the direction of the cursor. Viewport.Unproject is used
  153. // to accomplish this. see the accompanying documentation for more explanation
  154. // of the math behind this function.
  155. public Ray CalculateCursorRay(Matrix projectionMatrix, Matrix viewMatrix)
  156. {
  157. // create 2 positions in screenspace using the cursor position. 0 is as
  158. // close as possible to the camera, 1 is as far away as possible.
  159. Vector3 nearSource = new Vector3(Position, 0f);
  160. Vector3 farSource = new Vector3(Position, 1f);
  161. // use Viewport.Unproject to tell what those two screen space positions
  162. // would be in world space. we'll need the projection matrix and view
  163. // matrix, which we have saved as member variables. We also need a world
  164. // matrix, which can just be identity.
  165. Vector3 nearPoint = GraphicsDevice.Viewport.Unproject(nearSource,
  166. projectionMatrix, viewMatrix, Matrix.Identity);
  167. Vector3 farPoint = GraphicsDevice.Viewport.Unproject(farSource,
  168. projectionMatrix, viewMatrix, Matrix.Identity);
  169. // find the direction vector that goes from the nearPoint to the farPoint
  170. // and normalize it....
  171. Vector3 direction = farPoint - nearPoint;
  172. direction.Normalize();
  173. // and then create a new ray using nearPoint as the source.
  174. return new Ray(nearPoint, direction);
  175. }
  176. #endregion
  177. }
  178. }