Cursor.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Microsoft.Xna.Framework.Content;
  5. using Microsoft.Xna.Framework.Graphics;
  6. using Microsoft.Xna.Framework;
  7. using Microsoft.Xna.Framework.Input;
  8. namespace GooCursor
  9. {
  10. public class Cursor : DrawableGameComponent
  11. {
  12. private struct TrailNode
  13. {
  14. public Vector2 Position;
  15. public Vector2 Velocity;
  16. }
  17. // this is the sprite that is drawn at the current cursor position.
  18. // textureCenter is used to center the sprite when drawing.
  19. private Texture2D cursorTexture;
  20. private Vector2 textureCenter;
  21. private SpriteBatch spriteBatch;
  22. private Vector2 position;
  23. private int trailNodeCount;
  24. private TrailNode[] trailNodes;
  25. /// <summary>
  26. /// Gets of Sets the screen position of the cursor
  27. /// </summary>
  28. public Vector2 Position
  29. {
  30. get { return position; }
  31. set { position = value; }
  32. }
  33. /// <summary>
  34. /// Gets of Sets the stiffness of the trail
  35. /// A lower number means the trail will be longer
  36. /// </summary>
  37. public float TrailStiffness { get; set; }
  38. /// <summary>
  39. /// Controls the damping of the velocity of trail nodes
  40. /// </summary>
  41. public float TrailDamping { get; set; }
  42. /// <summary>
  43. /// Mass of a trails node
  44. /// </summary>
  45. public float TrailNodeMass { get; set; }
  46. /// <summary>
  47. /// Controls how fast the gamepad moves the cursor.
  48. /// Measured in pixels per second.
  49. /// </summary>
  50. public float CursorSpeed { get; set; }
  51. /// <summary>
  52. /// The scaling applied at the tip of the cursor
  53. /// </summary>
  54. public float StartScale { get; set; }
  55. /// <summary>
  56. /// The scaling applied at the end of the cursor
  57. /// </summary>
  58. public float EndScale { get; set; }
  59. /// <summary>
  60. /// use this to control the rate of change between the
  61. /// StartScale and the EndScale
  62. /// </summary>
  63. public float LerpExponent { get; set; }
  64. /// <summary>
  65. /// Color used to fill the cursor
  66. /// </summary>
  67. public Color FillColor { get; set; }
  68. /// <summary>
  69. /// color used for the cursor border
  70. /// </summary>
  71. public Color BorderColor { get; set; }
  72. /// <summary>
  73. /// Size of the border (in pixels)
  74. /// </summary>
  75. public float BorderSize { get; set; }
  76. public Cursor(Game game, int trailNodesNo, float stiffness, float damping)
  77. :base(game)
  78. {
  79. trailNodeCount = trailNodesNo;
  80. TrailStiffness = stiffness;
  81. TrailDamping = damping;
  82. trailNodes = new TrailNode[trailNodeCount];
  83. CursorSpeed = 600;
  84. StartScale = 1.0f;
  85. EndScale = 0.3f;
  86. LerpExponent = 0.5f;
  87. TrailNodeMass = 11.2f;
  88. FillColor = Color.Black;
  89. BorderColor = Color.White;
  90. BorderSize = 10;
  91. }
  92. public Cursor(Game game, int trailNodesNo)
  93. : this(game, trailNodesNo, 30000, 600)
  94. {
  95. }
  96. public Cursor(Game game)
  97. : this(game,50,30000,600)
  98. {
  99. }
  100. protected override void LoadContent()
  101. {
  102. cursorTexture = Game.Content.Load<Texture2D>("cursor");
  103. textureCenter = new Vector2(cursorTexture.Width / 2, cursorTexture.Height / 2);
  104. spriteBatch = new SpriteBatch(GraphicsDevice);
  105. base.LoadContent();
  106. }
  107. //we can center the cursor once we
  108. //know how big the viewport will be
  109. //this only really effects the 360 code
  110. //where no mouse is available
  111. public override void Initialize()
  112. {
  113. base.Initialize();
  114. Viewport vp = GraphicsDevice.Viewport;
  115. position.X = vp.X + (vp.Width / 2);
  116. position.Y = vp.Y + (vp.Height / 2);
  117. }
  118. public override void Draw(GameTime gameTime)
  119. {
  120. //spriteBatch.Begin SpriteBlendMode.AlphaBlend);
  121. //spriteBatch.Begin(0, BlendState.AlphaBlend);
  122. spriteBatch.Begin ();
  123. //First we draw all the trail nodes using the border color
  124. //we need to draw them slightly larger, so the border is left visible
  125. //later, when we draw the actual nodes
  126. //adjust the StartScale and EndScale to take into consideration the border
  127. float borderStartScale = StartScale + BorderSize / cursorTexture.Width;
  128. float borderEndScale = EndScale + BorderSize / cursorTexture.Width;
  129. //draw all nodes with the new scales
  130. for (int i = 0; i < trailNodeCount; i++)
  131. {
  132. TrailNode node = trailNodes[i];
  133. float lerpFactor = (float)i / (float)(trailNodeCount - 1);
  134. lerpFactor = (float)Math.Pow(lerpFactor, LerpExponent);
  135. float scale = MathHelper.Lerp(borderStartScale, borderEndScale, lerpFactor);
  136. //draw using the Border Color
  137. spriteBatch.Draw(cursorTexture, node.Position, null, BorderColor, 0.0f,
  138. textureCenter, scale, SpriteEffects.None, 0.0f);
  139. }
  140. //Next, we draw all the nodes normally, using the Fill Color
  141. //Because before we drew them larger, after we draw them at
  142. //their normal size, a border will remain visible.
  143. for (int i = 0; i < trailNodeCount; i++)
  144. {
  145. TrailNode node = trailNodes[i];
  146. float lerpFactor = (float)i / (float)(trailNodeCount - 1);
  147. lerpFactor = (float)Math.Pow(lerpFactor, LerpExponent);
  148. float scale = MathHelper.Lerp(StartScale, EndScale, lerpFactor);
  149. //draw using the fill color
  150. spriteBatch.Draw(cursorTexture, node.Position, null, FillColor, 0.0f,
  151. textureCenter, scale, SpriteEffects.None, 0.0f);
  152. }
  153. spriteBatch.End();
  154. }
  155. Vector2 deltaMovement;
  156. private void UpdateTrailNodes(float elapsed)
  157. {
  158. for (int i = 1; i < trailNodeCount; i++)
  159. {
  160. TrailNode tn = trailNodes[i];
  161. // Calculate spring force
  162. Vector2 stretch = tn.Position - trailNodes[i - 1].Position;
  163. Vector2 force = -TrailStiffness * stretch - TrailDamping * tn.Velocity;
  164. // Apply acceleration
  165. Vector2 acceleration = force / TrailNodeMass;
  166. tn.Velocity += acceleration * elapsed;
  167. // Apply velocity
  168. tn.Position += tn.Velocity * elapsed;
  169. trailNodes[i] = tn;
  170. }
  171. }
  172. public override void Update(GameTime gameTime)
  173. {
  174. // first, use the GamePad to update the cursor position
  175. // down on the thumbstick is -1. however, in screen coordinates, values
  176. // increase as they go down the screen. so, we have to flip the sign of the
  177. // y component of delta.
  178. deltaMovement = GamePad.GetState(PlayerIndex.One).ThumbSticks.Left;
  179. deltaMovement.Y *= -1;
  180. #if !XBOX360
  181. //use the mouse position as the cursor position
  182. MouseState mouseState = Mouse.GetState();
  183. position.X = mouseState.X;
  184. position.Y = mouseState.Y;
  185. #endif
  186. Console.WriteLine(position);
  187. // modify position using delta, the CursorSpeed, and
  188. // the elapsed game time.
  189. position += deltaMovement * CursorSpeed *
  190. (float)gameTime.ElapsedGameTime.TotalSeconds;
  191. #if XBOX360
  192. // clamp the cursor position to the viewport, so that it can't move off the
  193. // screen.
  194. Viewport vp = GraphicsDevice.Viewport;
  195. position.X = MathHelper.Clamp(position.X, vp.X, vp.X + vp.Width);
  196. position.Y = MathHelper.Clamp(position.Y, vp.Y, vp.Y + vp.Height);
  197. #else
  198. // set the new mouse position using the combination of mouse and gamepad data.
  199. Mouse.SetPosition((int)position.X, (int)position.Y);
  200. #endif
  201. //set position of first trail node;
  202. trailNodes[0].Position = position;
  203. //update the trails
  204. UpdateTrailNodes((float)gameTime.ElapsedGameTime.TotalSeconds);
  205. }
  206. }
  207. }