Accelerometer.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // Accelerometer.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.Input;
  13. #endregion
  14. namespace Platformer
  15. {
  16. /// <summary>
  17. /// A static encapsulation of accelerometer input to provide games with a polling-based
  18. /// accelerometer system.
  19. /// </summary>
  20. public static class Accelerometer
  21. {
  22. #if WINDOWS_PHONE
  23. // the accelerometer sensor on the device
  24. private static Microsoft.Devices.Sensors.Accelerometer accelerometer = new Microsoft.Devices.Sensors.Accelerometer();
  25. // we need an object for locking because the ReadingChanged event is fired
  26. // on a different thread than our game
  27. private static object threadLock = new object();
  28. // we use this to keep the last known value from the accelerometer callback
  29. private static Vector3 nextValue = new Vector3();
  30. #endif
  31. // we want to prevent the Accelerometer from being initialized twice.
  32. private static bool isInitialized = false;
  33. // whether or not the accelerometer is active
  34. private static bool isActive = false;
  35. /// <summary>
  36. /// Initializes the Accelerometer for the current game. This method can only be called once per game.
  37. /// </summary>
  38. public static void Initialize()
  39. {
  40. // make sure we don't initialize the Accelerometer twice
  41. if (isInitialized)
  42. {
  43. throw new InvalidOperationException("Initialize can only be called once");
  44. }
  45. #if WINDOWS_PHONE
  46. // try to start the sensor only on devices, catching the exception if it fails
  47. if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Device)
  48. {
  49. try
  50. {
  51. accelerometer.ReadingChanged += new EventHandler<Microsoft.Devices.Sensors.AccelerometerReadingEventArgs>(sensor_ReadingChanged);
  52. accelerometer.Start();
  53. isActive = true;
  54. }
  55. catch (Microsoft.Devices.Sensors.AccelerometerFailedException)
  56. {
  57. isActive = false;
  58. }
  59. }
  60. else
  61. {
  62. // we always return isActive on emulator because we use the arrow
  63. // keys for simulation which is always available.
  64. isActive = true;
  65. }
  66. #endif
  67. // remember that we are initialized
  68. isInitialized = true;
  69. }
  70. #if WINDOWS_PHONE
  71. private static void sensor_ReadingChanged(object sender, Microsoft.Devices.Sensors.AccelerometerReadingEventArgs e)
  72. {
  73. // store the accelerometer value in our variable to be used on the next Update
  74. lock (threadLock)
  75. {
  76. nextValue = new Vector3((float)e.X, (float)e.Y, (float)e.Z);
  77. }
  78. }
  79. #endif
  80. /// <summary>
  81. /// Gets the current state of the accelerometer.
  82. /// </summary>
  83. /// <returns>A new AccelerometerState with the current state of the accelerometer.</returns>
  84. public static AccelerometerState GetState()
  85. {
  86. // make sure we've initialized the Accelerometer before we try to get the state
  87. if (!isInitialized)
  88. {
  89. throw new InvalidOperationException("You must Initialize before you can call GetState");
  90. }
  91. // create a new value for our state
  92. Vector3 stateValue = new Vector3();
  93. #if WINDOWS_PHONE
  94. // if the accelerometer is active
  95. if (isActive)
  96. {
  97. if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Device)
  98. {
  99. // if we're on device, we'll just grab our latest reading from the accelerometer
  100. lock (threadLock)
  101. {
  102. stateValue = nextValue;
  103. }
  104. }
  105. else
  106. {
  107. // if we're in the emulator, we'll generate a fake acceleration value using the arrow keys
  108. // press the pause/break key to toggle keyboard input for the emulator
  109. KeyboardState keyboardState = Keyboard.GetState();
  110. stateValue.Z = -1;
  111. if (keyboardState.IsKeyDown(Keys.Left))
  112. stateValue.X--;
  113. if (keyboardState.IsKeyDown(Keys.Right))
  114. stateValue.X++;
  115. if (keyboardState.IsKeyDown(Keys.Up))
  116. stateValue.Y++;
  117. if (keyboardState.IsKeyDown(Keys.Down))
  118. stateValue.Y--;
  119. stateValue.Normalize();
  120. }
  121. }
  122. #endif
  123. return new AccelerometerState(stateValue, isActive);
  124. }
  125. }
  126. /// <summary>
  127. /// An encapsulation of the accelerometer's current state.
  128. /// </summary>
  129. public struct AccelerometerState
  130. {
  131. /// <summary>
  132. /// Gets the accelerometer's current value in G-force.
  133. /// </summary>
  134. public Vector3 Acceleration { get; private set; }
  135. /// <summary>
  136. /// Gets whether or not the accelerometer is active and running.
  137. /// </summary>
  138. public bool IsActive { get; private set; }
  139. /// <summary>
  140. /// Initializes a new AccelerometerState.
  141. /// </summary>
  142. /// <param name="acceleration">The current acceleration (in G-force) of the accelerometer.</param>
  143. /// <param name="isActive">Whether or not the accelerometer is active.</param>
  144. public AccelerometerState(Vector3 acceleration, bool isActive)
  145. : this()
  146. {
  147. Acceleration = acceleration;
  148. IsActive = isActive;
  149. }
  150. /// <summary>
  151. /// Returns a string containing the values of the Acceleration and IsActive properties.
  152. /// </summary>
  153. /// <returns>A new string describing the state.</returns>
  154. public override string ToString()
  155. {
  156. return string.Format("Acceleration: {0}, IsActive: {1}", Acceleration, IsActive);
  157. }
  158. }
  159. }