#region File Description //----------------------------------------------------------------------------- // Accelerometer.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; #endregion namespace Platformer { /// /// A static encapsulation of accelerometer input to provide games with a polling-based /// accelerometer system. /// public static class Accelerometer { #if WINDOWS_PHONE // the accelerometer sensor on the device private static Microsoft.Devices.Sensors.Accelerometer accelerometer = new Microsoft.Devices.Sensors.Accelerometer(); // we need an object for locking because the ReadingChanged event is fired // on a different thread than our game private static object threadLock = new object(); // we use this to keep the last known value from the accelerometer callback private static Vector3 nextValue = new Vector3(); #endif // we want to prevent the Accelerometer from being initialized twice. private static bool isInitialized = false; // whether or not the accelerometer is active private static bool isActive = false; /// /// Initializes the Accelerometer for the current game. This method can only be called once per game. /// public static void Initialize() { // make sure we don't initialize the Accelerometer twice if (isInitialized) { throw new InvalidOperationException("Initialize can only be called once"); } #if WINDOWS_PHONE // try to start the sensor only on devices, catching the exception if it fails if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Device) { try { accelerometer.ReadingChanged += new EventHandler(sensor_ReadingChanged); accelerometer.Start(); isActive = true; } catch (Microsoft.Devices.Sensors.AccelerometerFailedException) { isActive = false; } } else { // we always return isActive on emulator because we use the arrow // keys for simulation which is always available. isActive = true; } #endif // remember that we are initialized isInitialized = true; } #if WINDOWS_PHONE private static void sensor_ReadingChanged(object sender, Microsoft.Devices.Sensors.AccelerometerReadingEventArgs e) { // store the accelerometer value in our variable to be used on the next Update lock (threadLock) { nextValue = new Vector3((float)e.X, (float)e.Y, (float)e.Z); } } #endif /// /// Gets the current state of the accelerometer. /// /// A new AccelerometerState with the current state of the accelerometer. public static AccelerometerState GetState() { // make sure we've initialized the Accelerometer before we try to get the state if (!isInitialized) { throw new InvalidOperationException("You must Initialize before you can call GetState"); } // create a new value for our state Vector3 stateValue = new Vector3(); #if WINDOWS_PHONE // if the accelerometer is active if (isActive) { if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Device) { // if we're on device, we'll just grab our latest reading from the accelerometer lock (threadLock) { stateValue = nextValue; } } else { // if we're in the emulator, we'll generate a fake acceleration value using the arrow keys // press the pause/break key to toggle keyboard input for the emulator KeyboardState keyboardState = Keyboard.GetState(); stateValue.Z = -1; if (keyboardState.IsKeyDown(Keys.Left)) stateValue.X--; if (keyboardState.IsKeyDown(Keys.Right)) stateValue.X++; if (keyboardState.IsKeyDown(Keys.Up)) stateValue.Y++; if (keyboardState.IsKeyDown(Keys.Down)) stateValue.Y--; stateValue.Normalize(); } } #endif return new AccelerometerState(stateValue, isActive); } } /// /// An encapsulation of the accelerometer's current state. /// public struct AccelerometerState { /// /// Gets the accelerometer's current value in G-force. /// public Vector3 Acceleration { get; private set; } /// /// Gets whether or not the accelerometer is active and running. /// public bool IsActive { get; private set; } /// /// Initializes a new AccelerometerState. /// /// The current acceleration (in G-force) of the accelerometer. /// Whether or not the accelerometer is active. public AccelerometerState(Vector3 acceleration, bool isActive) : this() { Acceleration = acceleration; IsActive = isActive; } /// /// Returns a string containing the values of the Acceleration and IsActive properties. /// /// A new string describing the state. public override string ToString() { return string.Format("Acceleration: {0}, IsActive: {1}", Acceleration, IsActive); } } }