Cursor.cs 9.1 KB

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