#region File Description //----------------------------------------------------------------------------- // InputState.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input.Touch; using System.Collections.Generic; #endregion namespace HoneycombRush { /// /// Helper for reading input from keyboard, gamepad, and touch input. This class /// tracks both the current and previous state of the input devices, and implements /// query methods for high level input actions such as "move up through the menu" /// or "pause the game". /// public class InputState { public enum MouseButton { Left, Middle, Right } #region Fields public const int MaxInputs = 4; public readonly KeyboardState[] CurrentKeyboardStates; public readonly MouseState[] CurrentMouseStates; public readonly GamePadState[] CurrentGamePadStates; public readonly KeyboardState[] LastKeyboardStates; public readonly MouseState[] LastMouseStates; public readonly GamePadState[] LastGamePadStates; public readonly bool[] GamePadWasConnected; public TouchCollection TouchState; public readonly List Gestures = new List(); #endregion #region Initialization /// /// Constructs a new input state. /// public InputState() { CurrentKeyboardStates = new KeyboardState[MaxInputs]; CurrentMouseStates = new MouseState[MaxInputs]; CurrentGamePadStates = new GamePadState[MaxInputs]; LastKeyboardStates = new KeyboardState[MaxInputs]; LastMouseStates = new MouseState[MaxInputs]; LastGamePadStates = new GamePadState[MaxInputs]; GamePadWasConnected = new bool[MaxInputs]; } #endregion #region Public Methods /// /// Reads the latest state of the keyboard and gamepad. /// public void Update() { for (int i = 0; i < MaxInputs; i++) { LastKeyboardStates[i] = CurrentKeyboardStates[i]; LastMouseStates[i] = CurrentMouseStates[i]; LastGamePadStates[i] = CurrentGamePadStates[i]; CurrentKeyboardStates[i] = Keyboard.GetState((PlayerIndex)i); CurrentMouseStates[i] = Mouse.GetState(); CurrentGamePadStates[i] = GamePad.GetState((PlayerIndex)i); // Keep track of whether a gamepad has ever been // connected, so we can detect if it is unplugged. if (CurrentGamePadStates[i].IsConnected) { GamePadWasConnected[i] = true; } } TouchState = TouchPanel.GetState(); Gestures.Clear(); while (TouchPanel.IsGestureAvailable) { Gestures.Add(TouchPanel.ReadGesture()); } } /// /// Helper for checking if a key was newly pressed during this update. The /// controllingPlayer parameter specifies which player to read input for. /// If this is null, it will accept input from any player. When a keypress /// is detected, the output playerIndex reports which player pressed it. /// public bool IsNewKeyPress(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) { if (controllingPlayer.HasValue) { // Read input from the specified player. playerIndex = controllingPlayer.Value; int i = (int)playerIndex; return (CurrentKeyboardStates[i].IsKeyDown(key) && LastKeyboardStates[i].IsKeyUp(key)); } else { // Accept input from any player. return (IsNewKeyPress(key, PlayerIndex.One, out playerIndex) || IsNewKeyPress(key, PlayerIndex.Two, out playerIndex) || IsNewKeyPress(key, PlayerIndex.Three, out playerIndex) || IsNewKeyPress(key, PlayerIndex.Four, out playerIndex)); } } /// /// Helper for checking if a key is currently pressed during the update. The /// controllingPlayer parameter specifies which player to read input for. /// If this is null, it will accept input from any player. When a pressed key /// is detected, the output playerIndex reports which player pressed it. /// public bool IsKeyDown(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) { if (controllingPlayer.HasValue) { // Read input from the specified player. playerIndex = controllingPlayer.Value; int i = (int)playerIndex; return (CurrentKeyboardStates[i].IsKeyDown(key)); } else { // Accept input from any player. return (IsKeyDown(key, PlayerIndex.One, out playerIndex) || IsKeyDown(key, PlayerIndex.Two, out playerIndex) || IsKeyDown(key, PlayerIndex.Three, out playerIndex) || IsKeyDown(key, PlayerIndex.Four, out playerIndex)); } } /// /// Helper for checking if a mouse button was newly pressed during this update. The /// controllingPlayer parameter specifies which player to read input for. /// If this is null, it will accept input from any player. When a click /// is detected, the output playerIndex reports which player pressed it. /// public bool IsNewMouseClick(MouseButton mouseButton , PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) { if (controllingPlayer.HasValue) { // Read input from the specified player. playerIndex = controllingPlayer.Value; int i = (int)playerIndex; switch( mouseButton){ case MouseButton.Left: return (CurrentMouseStates[i].LeftButton == ButtonState.Pressed && LastMouseStates[i].LeftButton == ButtonState.Released); case MouseButton.Right: return (CurrentMouseStates[i].RightButton == ButtonState.Pressed && LastMouseStates[i].RightButton == ButtonState.Released); case MouseButton.Middle: return (CurrentMouseStates[i].MiddleButton == ButtonState.Pressed && LastMouseStates[i].MiddleButton == ButtonState.Released); default: return IsNewMouseClick(MouseButton.Left, controllingPlayer, out playerIndex) || IsNewMouseClick(MouseButton.Middle, controllingPlayer, out playerIndex) || IsNewMouseClick(MouseButton.Right, controllingPlayer, out playerIndex); } } else { // Accept input from any player. return (IsNewMouseClick(mouseButton, PlayerIndex.One, out playerIndex) || IsNewMouseClick(mouseButton, PlayerIndex.Two, out playerIndex) || IsNewMouseClick(mouseButton, PlayerIndex.Three, out playerIndex) || IsNewMouseClick(mouseButton, PlayerIndex.Four, out playerIndex)); } } /// /// Helper for checking if a mouse button is currently pressed during the update. The /// controllingPlayer parameter specifies which player to read input for. /// If this is null, it will accept input from any player. When a pressed button /// is detected, the output playerIndex reports which player pressed it. /// public bool IsMouseDown(MouseButton mouseButton , PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) { if (controllingPlayer.HasValue) { // Read input from the specified player. playerIndex = controllingPlayer.Value; int i = (int)playerIndex; switch( mouseButton ) { case MouseButton.Left: return CurrentMouseStates[i].LeftButton == ButtonState.Pressed; case MouseButton.Right: return CurrentMouseStates[i].RightButton == ButtonState.Pressed; case MouseButton.Middle: return CurrentMouseStates[i].MiddleButton == ButtonState.Pressed; default: return IsMouseDown(MouseButton.Left, controllingPlayer, out playerIndex) || IsMouseDown(MouseButton.Middle, controllingPlayer, out playerIndex) || IsMouseDown(MouseButton.Right, controllingPlayer, out playerIndex); } } else { // Accept input from any player. return (IsMouseDown(mouseButton, PlayerIndex.One, out playerIndex) || IsMouseDown(mouseButton, PlayerIndex.Two, out playerIndex) || IsMouseDown(mouseButton, PlayerIndex.Three, out playerIndex) || IsMouseDown(mouseButton, PlayerIndex.Four, out playerIndex)); } } /// /// Helper for checking if a button was newly pressed during this update. /// The controllingPlayer parameter specifies which player to read input for. /// If this is null, it will accept input from any player. When a button press /// is detected, the output playerIndex reports which player pressed it. /// public bool IsNewButtonPress(Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) { if (controllingPlayer.HasValue) { // Read input from the specified player. playerIndex = controllingPlayer.Value; int i = (int)playerIndex; return (CurrentGamePadStates[i].IsButtonDown(button) && LastGamePadStates[i].IsButtonUp(button)); } else { // Accept input from any player. return (IsNewButtonPress(button, PlayerIndex.One, out playerIndex) || IsNewButtonPress(button, PlayerIndex.Two, out playerIndex) || IsNewButtonPress(button, PlayerIndex.Three, out playerIndex) || IsNewButtonPress(button, PlayerIndex.Four, out playerIndex)); } } /// /// Checks for a "menu select" input action. /// The controllingPlayer parameter specifies which player to read input for. /// If this is null, it will accept input from any player. When the action /// is detected, the output playerIndex reports which player pressed it. /// public bool IsMenuSelect(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) { return IsNewKeyPress(Keys.Space, controllingPlayer, out playerIndex) || IsNewKeyPress(Keys.Enter, controllingPlayer, out playerIndex) || IsNewMouseClick(MouseButton.Left, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.A, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.Start, controllingPlayer, out playerIndex); } /// /// Checks for a "menu cancel" input action. /// The controllingPlayer parameter specifies which player to read input for. /// If this is null, it will accept input from any player. When the action /// is detected, the output playerIndex reports which player pressed it. /// public bool IsMenuCancel(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex) { return IsNewKeyPress(Keys.Escape, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.B, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.Back, controllingPlayer, out playerIndex); } /// /// Checks for a "menu up" input action. /// The controllingPlayer parameter specifies which player to read /// input for. If this is null, it will accept input from any player. /// public bool IsMenuUp(PlayerIndex? controllingPlayer) { PlayerIndex playerIndex; return IsNewKeyPress(Keys.Up, controllingPlayer, out playerIndex) || IsNewKeyPress(Keys.Left, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.DPadLeft, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.LeftThumbstickLeft, controllingPlayer, out playerIndex); } /// /// Checks for a "menu down" input action. /// The controllingPlayer parameter specifies which player to read /// input for. If this is null, it will accept input from any player. /// public bool IsMenuDown(PlayerIndex? controllingPlayer) { PlayerIndex playerIndex; return IsNewKeyPress(Keys.Down, controllingPlayer, out playerIndex) || IsNewKeyPress(Keys.Right, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.DPadRight, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.LeftThumbstickRight, controllingPlayer, out playerIndex); } /// /// Checks for a "pause the game" input action. /// The controllingPlayer parameter specifies which player to read /// input for. If this is null, it will accept input from any player. /// public bool IsPauseGame(PlayerIndex? controllingPlayer) { PlayerIndex playerIndex; return IsNewKeyPress(Keys.Escape, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.Back, controllingPlayer, out playerIndex) || IsNewButtonPress(Buttons.Start, controllingPlayer, out playerIndex); } #endregion } }