// Project: XnaShooter, File: Input.cs // Namespace: XnaShooter.Helpers, Class: Input // Path: C:\code\XnaBook\XnaShooter\Helpers, Author: abi // Code lines: 931, Size of file: 24,39 KB // Creation date: 07.12.2006 18:22 // Last modified: 07.12.2006 21:54 // Generated with Commenter by abi.exDream.com #region Using directives using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using XnaShooter.Helpers; using System; using System.Collections.Generic; using System.Text; using System.Threading; using XnaShooter.Game; using XnaShooter.Graphics; #endregion namespace XnaShooter.Helpers { /// /// Input helper class, captures all the mouse, keyboard and XBox 360 /// controller input and provides some nice helper methods and properties. /// Will also keep track of the last frame states for comparison if /// a button was just pressed this frame, but not already in the last frame. /// class Input { #region Variables #if !XBOX360 /// /// Mouse state, set every frame in the Update method. /// private static MouseState mouseState, mouseStateLastFrame; #else /// /// Just save the mouse position here, it is just virtual on the Xbox. /// Clicking is not possible .. we got no mouse support on the Xbox. /// private static Point mouseState, mouseStateLastFrame; #endif /// /// Was a mouse detected? Returns true if the user moves the mouse. /// On the Xbox 360 there will be no mouse movement and theirfore we /// know that we don't have to display the mouse. /// private static bool mouseDetected = false; /// /// Keyboard state, set every frame in the Update method. /// Note: KeyboardState is a class and not a struct, /// we have to initialize it here, else we might run into trouble when /// accessing any keyboardState data before BaseGame.Update() is called. /// We can also NOT use the last state because everytime we call /// Keyboard.GetState() the old state is useless (see XNA help for more /// information, section Input). We store our own array of keys from /// the last frame for comparing stuff. /// private static KeyboardState keyboardState = Microsoft.Xna.Framework.Input.Keyboard.GetState(); /// /// Keys pressed last frame, for comparison if a key was just pressed. /// private static List keysPressedLastFrame = new List(); /// /// GamePad state, set every frame in the Update method. /// private static GamePadState gamePadState, gamePadStateLastFrame; /// /// Mouse wheel delta this frame. XNA does report only the total /// scroll value, but we usually need the current delta! /// /// 0 #if XBOX360 private static int mouseWheelDelta = 0; #else private static int mouseWheelDelta = 0, mouseWheelValue = 0; #endif /// /// Start dragging pos, will be set when we just pressed the left /// mouse button. Used for the MouseDraggingAmount property. /// private static Point startDraggingPos; #endregion #region Mouse Properties /// /// Was a mouse detected? Returns true if the user moves the mouse. /// On the Xbox 360 there will be no mouse movement and theirfore we /// know that we don't have to display the mouse. /// /// Bool public static bool MouseDetected { get { return mouseDetected; } // get } // MouseDetected /// /// Mouse position /// /// Point public static Point MousePos { get { #if XBOX360 return mouseState; #else return new Point(mouseState.X, mouseState.Y); #endif } // get set { #if XBOX360 mouseState = value; #else Mouse.SetPosition(value.X, value.Y); #endif } // set } // MousePos #if !XBOX360 private static bool mouseWasCentered = false; #endif /// /// Center mouse on screen for optimal mouse movement. /// This is required because mouse movement is absolute and /// relative mode is not supported like in DirectX. /// We have to make sure in the next frame the relative movement will /// still be correct! /// public static void CenterMouse() { #if !XBOX360 mouseWasCentered = true; #endif } // CenterMouse() #if !XBOX360 /// /// X and y movements of the mouse this frame /// private static float mouseXMovement, mouseYMovement, lastMouseXMovement, lastMouseYMovement; #endif /// /// Mouse x movement /// /// Float public static float MouseXMovement { get { #if XBOX360 return 0; #else return mouseXMovement; #endif } // get } // MouseXMovement /// /// Mouse y movement /// /// Float public static float MouseYMovement { get { #if XBOX360 return 0; #else return mouseYMovement; #endif } // get } // MouseYMovement /// /// Mouse left button pressed /// /// Bool public static bool MouseLeftButtonPressed { get { #if XBOX360 return false; #else return mouseState.LeftButton == ButtonState.Pressed; #endif } // get } // MouseLeftButtonPressed /// /// Mouse right button pressed /// /// Bool public static bool MouseRightButtonPressed { get { #if XBOX360 return false; #else return mouseState.RightButton == ButtonState.Pressed; #endif } // get } // MouseRightButtonPressed /// /// Mouse middle button pressed /// /// Bool public static bool MouseMiddleButtonPressed { get { #if XBOX360 return false; #else return mouseState.MiddleButton == ButtonState.Pressed; #endif } // get } // MouseMiddleButtonPressed /// /// Mouse left button just pressed /// /// Bool public static bool MouseLeftButtonJustPressed { get { #if XBOX360 return false; #else return mouseState.LeftButton == ButtonState.Pressed && mouseStateLastFrame.LeftButton == ButtonState.Released; #endif } // get } // MouseLeftButtonJustPressed /// /// Mouse right button just pressed /// /// Bool public static bool MouseRightButtonJustPressed { get { #if XBOX360 return false; #else return mouseState.RightButton == ButtonState.Pressed && mouseStateLastFrame.RightButton == ButtonState.Released; #endif } // get } // MouseRightButtonJustPressed /// /// Mouse dragging amount /// /// Point public static Point MouseDraggingAmount { get { return new Point( startDraggingPos.X - MousePos.X, startDraggingPos.Y - MousePos.Y); } // get } // MouseDraggingAmount /// /// Reset mouse dragging amount /// public static void ResetMouseDraggingAmount() { startDraggingPos = MousePos; } // ResetMouseDraggingAmount() /// /// Mouse wheel delta /// /// Int public static int MouseWheelDelta { get { return mouseWheelDelta; } // get } // MouseWheelDelta /// /// Mouse in box /// /// Rectangle /// Bool public static bool MouseInBox(Rectangle rect) { bool ret = mouseState.X >= rect.X && mouseState.Y >= rect.Y && mouseState.X < rect.Right && mouseState.Y < rect.Bottom; return ret; } // MouseInBox(rect) /// /// Mouse was not in rectangle last frame /// /// Rectangle public static bool MouseWasNotInRectLastFrame(Rectangle rect) { // Check the opposite of MouseInBox. bool lastRet = mouseStateLastFrame.X >= rect.X && mouseStateLastFrame.Y >= rect.Y && mouseStateLastFrame.X < rect.Right && mouseStateLastFrame.Y < rect.Bottom; return !lastRet; } // MouseWasNotInRectLastFrame(rect) #endregion #region Keyboard Properties /// /// Keyboard /// /// Keyboard state public static KeyboardState Keyboard { get { return keyboardState; } // get } // Keyboard public static bool IsSpecialKey(Keys key) { // All keys except A-Z, 0-9 and `-\[];',./= (and space) are special keys. // With shift pressed this also results in this keys: // ~_|{}:"<>? !@#$%^&*(). int keyNum = (int)key; if ((keyNum >= (int)Keys.A && keyNum <= (int)Keys.Z) || (keyNum >= (int)Keys.D0 && keyNum <= (int)Keys.D9) || key == Keys.Space || // well, space ^^ key == Keys.OemTilde || // `~ key == Keys.OemMinus || // -_ key == Keys.OemPipe || // \| key == Keys.OemOpenBrackets || // [{ key == Keys.OemCloseBrackets || // ]} key == Keys.OemSemicolon || // ;: key == Keys.OemQuotes || // '" key == Keys.OemComma || // ,< key == Keys.OemPeriod || // .> key == Keys.OemQuestion || // /? key == Keys.OemPlus) // =+ return false; // Else is is a special key return true; } // static bool IsSpecialKey(Keys key) /// /// Keys to char helper conversion method. /// Note: If the keys are mapped other than on a default QWERTY /// keyboard, this method will not work properly. Most keyboards /// will return the same for A-Z and 0-9, but the special keys /// might be different. Sorry, no easy way to fix this with XNA ... /// For a game with chat (windows) you should implement the /// windows events for catching keyboard input, which are much better! /// /// Keys /// Char public static char KeyToChar(Keys key, bool shiftPressed) { // If key will not be found, just return space char ret = ' '; int keyNum = (int)key; if (keyNum >= (int)Keys.A && keyNum <= (int)Keys.Z) { if (shiftPressed) ret = key.ToString()[0]; else ret = key.ToString().ToLower()[0]; } // if (keyNum) else if (keyNum >= (int)Keys.D0 && keyNum <= (int)Keys.D9 && shiftPressed == false) { ret = (char)((int)'0' + (keyNum - Keys.D0)); } // else if else if (key == Keys.D1 && shiftPressed) ret = '!'; else if (key == Keys.D2 && shiftPressed) ret = '@'; else if (key == Keys.D3 && shiftPressed) ret = '#'; else if (key == Keys.D4 && shiftPressed) ret = '$'; else if (key == Keys.D5 && shiftPressed) ret = '%'; else if (key == Keys.D6 && shiftPressed) ret = '^'; else if (key == Keys.D7 && shiftPressed) ret = '&'; else if (key == Keys.D8 && shiftPressed) ret = '*'; else if (key == Keys.D9 && shiftPressed) ret = '('; else if (key == Keys.D0 && shiftPressed) ret = ')'; else if (key == Keys.OemTilde) ret = shiftPressed ? '~' : '`'; else if (key == Keys.OemMinus) ret = shiftPressed ? '_' : '-'; else if (key == Keys.OemPipe) ret = shiftPressed ? '|' : '\\'; else if (key == Keys.OemOpenBrackets) ret = shiftPressed ? '{' : '['; else if (key == Keys.OemCloseBrackets) ret = shiftPressed ? '}' : ']'; else if (key == Keys.OemSemicolon) ret = shiftPressed ? ':' : ';'; else if (key == Keys.OemQuotes) ret = shiftPressed ? '"' : '\''; else if (key == Keys.OemComma) ret = shiftPressed ? '<' : '.'; else if (key == Keys.OemPeriod) ret = shiftPressed ? '>' : ','; else if (key == Keys.OemQuestion) ret = shiftPressed ? '?' : '/'; else if (key == Keys.OemPlus) ret = shiftPressed ? '+' : '='; // Return result return ret; } // KeyToChar(key) /// /// Handle keyboard input helper method to catch keyboard input /// for an input text. Only used to enter the player name in the game. /// /// Input text public static void HandleKeyboardInput(ref string inputText) { // Is a shift key pressed (we have to check both, left and right) bool isShiftPressed = keyboardState.IsKeyDown(Keys.LeftShift) || keyboardState.IsKeyDown(Keys.RightShift); // Go through all pressed keys foreach (Keys pressedKey in keyboardState.GetPressedKeys()) // Only process if it was not pressed last frame if (keysPressedLastFrame.Contains(pressedKey) == false) { // No special key? if (IsSpecialKey(pressedKey) == false && // Max. allow 32 chars inputText.Length < 32) { // Then add the letter to our inputText. // Check also the shift state! inputText += KeyToChar(pressedKey, isShiftPressed); } // if (IsSpecialKey) else if (pressedKey == Keys.Back && inputText.Length > 0) { // Remove 1 character at end inputText = inputText.Substring(0, inputText.Length - 1); } // else if } // foreach if (WasKeyPressedLastFrame) } // HandleKeyboardInput(inputText) /// /// Keyboard key just pressed /// /// Bool public static bool KeyboardKeyJustPressed(Keys key) { return keyboardState.IsKeyDown(key) && keysPressedLastFrame.Contains(key) == false; } // KeyboardSpaceJustPressed /// /// Keyboard space just pressed /// /// Bool public static bool KeyboardSpaceJustPressed { get { return keyboardState.IsKeyDown(Keys.Space) && keysPressedLastFrame.Contains(Keys.Space) == false; } // get } // KeyboardSpaceJustPressed /// /// Keyboard F1 just pressed /// /// Bool public static bool KeyboardF1JustPressed { get { return keyboardState.IsKeyDown(Keys.F1) && keysPressedLastFrame.Contains(Keys.F1) == false; } // get } // KeyboardF1JustPressed /// /// Keyboard escape just pressed /// /// Bool public static bool KeyboardEscapeJustPressed { get { return keyboardState.IsKeyDown(Keys.Escape) && keysPressedLastFrame.Contains(Keys.Escape) == false; } // get } // KeyboardEscapeJustPressed /// /// Keyboard left just pressed /// /// Bool public static bool KeyboardLeftJustPressed { get { return keyboardState.IsKeyDown(Keys.Left) && keysPressedLastFrame.Contains(Keys.Left) == false; } // get } // KeyboardLeftJustPressed /// /// Keyboard right just pressed /// /// Bool public static bool KeyboardRightJustPressed { get { return keyboardState.IsKeyDown(Keys.Right) && keysPressedLastFrame.Contains(Keys.Right) == false; } // get } // KeyboardRightJustPressed /// /// Keyboard up just pressed /// /// Bool public static bool KeyboardUpJustPressed { get { return keyboardState.IsKeyDown(Keys.Up) && keysPressedLastFrame.Contains(Keys.Up) == false; } // get } // KeyboardUpJustPressed /// /// Keyboard down just pressed /// /// Bool public static bool KeyboardDownJustPressed { get { return keyboardState.IsKeyDown(Keys.Down) && keysPressedLastFrame.Contains(Keys.Down) == false; } // get } // KeyboardDownJustPressed /// /// Keyboard left pressed /// /// Bool public static bool KeyboardLeftPressed { get { return keyboardState.IsKeyDown(Keys.Left); } // get } // KeyboardLeftPressed /// /// Keyboard right pressed /// /// Bool public static bool KeyboardRightPressed { get { return keyboardState.IsKeyDown(Keys.Right); } // get } // KeyboardRightPressed /// /// Keyboard up pressed /// /// Bool public static bool KeyboardUpPressed { get { return keyboardState.IsKeyDown(Keys.Up); } // get } // KeyboardUpPressed /// /// Keyboard down pressed /// /// Bool public static bool KeyboardDownPressed { get { return keyboardState.IsKeyDown(Keys.Down); } // get } // KeyboardDownPressed #endregion #region GamePad Properties /// /// Game pad /// /// Game pad state public static GamePadState GamePad { get { return gamePadState; } // get } // GamePad /// /// Is game pad connected /// /// Bool public static bool IsGamePadConnected { get { return gamePadState.IsConnected; } // get } // IsGamePadConnected /// /// Game pad start pressed /// /// Bool public static bool GamePadStartPressed { get { return gamePadState.Buttons.Start == ButtonState.Pressed; } // get } // GamePadStartPressed /// /// Game pad a pressed /// /// Bool public static bool GamePadAPressed { get { return gamePadState.Buttons.A == ButtonState.Pressed; } // get } // GamePadAPressed /// /// Game pad b pressed /// /// Bool public static bool GamePadBPressed { get { return gamePadState.Buttons.B == ButtonState.Pressed; } // get } // GamePadBPressed /// /// Game pad x pressed /// /// Bool public static bool GamePadXPressed { get { return gamePadState.Buttons.X == ButtonState.Pressed; } // get } // GamePadXPressed /// /// Game pad y pressed /// /// Bool public static bool GamePadYPressed { get { return gamePadState.Buttons.Y == ButtonState.Pressed; } // get } // GamePadYPressed /// /// Game pad left pressed /// /// Bool public static bool GamePadLeftPressed { get { return gamePadState.DPad.Left == ButtonState.Pressed || gamePadState.ThumbSticks.Left.X < -0.75f; } // get } // GamePadLeftPressed /// /// Game pad right pressed /// /// Bool public static bool GamePadRightPressed { get { return gamePadState.DPad.Left == ButtonState.Pressed || gamePadState.ThumbSticks.Left.X > 0.75f; } // get } // GamePadRightPressed /// /// Game pad left just pressed /// /// Bool public static bool GamePadLeftJustPressed { get { return (gamePadState.DPad.Left == ButtonState.Pressed && gamePadStateLastFrame.DPad.Left == ButtonState.Released) || (gamePadState.ThumbSticks.Left.X < -0.75f && gamePadStateLastFrame.ThumbSticks.Left.X > -0.75f); } // get } // GamePadLeftJustPressed /// /// Game pad right just pressed /// /// Bool public static bool GamePadRightJustPressed { get { return (gamePadState.DPad.Right == ButtonState.Pressed && gamePadStateLastFrame.DPad.Right == ButtonState.Released) || (gamePadState.ThumbSticks.Left.X > 0.75f && gamePadStateLastFrame.ThumbSticks.Left.X < 0.75f); } // get } // GamePadRightJustPressed /// /// Game pad up just pressed /// /// Bool public static bool GamePadUpJustPressed { get { return (gamePadState.DPad.Up == ButtonState.Pressed && gamePadStateLastFrame.DPad.Up == ButtonState.Released) || (gamePadState.ThumbSticks.Left.Y > 0.75f && gamePadStateLastFrame.ThumbSticks.Left.Y < 0.75f); } // get } // GamePadUpJustPressed /// /// Game pad down just pressed /// /// Bool public static bool GamePadDownJustPressed { get { return (gamePadState.DPad.Down == ButtonState.Pressed && gamePadStateLastFrame.DPad.Down == ButtonState.Released) || (gamePadState.ThumbSticks.Left.Y < -0.75f && gamePadStateLastFrame.ThumbSticks.Left.Y > -0.75f); } // get } // GamePadDownJustPressed /// /// Game pad up pressed /// /// Bool public static bool GamePadUpPressed { get { return gamePadState.DPad.Down == ButtonState.Pressed || gamePadState.ThumbSticks.Left.Y > 0.75f; } // get } // GamePadUpPressed /// /// Game pad down pressed /// /// Bool public static bool GamePadDownPressed { get { return gamePadState.DPad.Up == ButtonState.Pressed || gamePadState.ThumbSticks.Left.Y < -0.75f; } // get } // GamePadDownPressed /// /// Game pad a just pressed /// /// Bool public static bool GamePadAJustPressed { get { return gamePadState.Buttons.A == ButtonState.Pressed && gamePadStateLastFrame.Buttons.A == ButtonState.Released; } // get } // GamePadAJustPressed /// /// Game pad b just pressed /// /// Bool public static bool GamePadBJustPressed { get { return gamePadState.Buttons.B == ButtonState.Pressed && gamePadStateLastFrame.Buttons.B == ButtonState.Released; } // get } // GamePadBJustPressed /// /// Game pad x just pressed /// /// Bool public static bool GamePadXJustPressed { get { return gamePadState.Buttons.X == ButtonState.Pressed && gamePadStateLastFrame.Buttons.X == ButtonState.Released; } // get } // GamePadXJustPressed /// /// Game pad y just pressed /// /// Bool public static bool GamePadYJustPressed { get { return gamePadState.Buttons.Y == ButtonState.Pressed && gamePadStateLastFrame.Buttons.Y == ButtonState.Released; } // get } // GamePadYJustPressed /// /// Game pad back just pressed /// /// Bool public static bool GamePadBackJustPressed { get { return gamePadState.Buttons.Back == ButtonState.Pressed && gamePadStateLastFrame.Buttons.Back == ButtonState.Released; } // get } // GamePadBackJustPressed private static float leftRumble = 0, rightRumble = 0; /// /// Game pad rumble /// /// Set left rumble /// Set right rumble public static void GamePadRumble(float setLeftRumble, float setRightRumble) { if (setLeftRumble > leftRumble) leftRumble = setLeftRumble; if (setRightRumble > rightRumble) rightRumble = setRightRumble; } // GamePadRumble(setLeftRumble, setRightRumble) #endregion #region Update /// /// Update, called from BaseGame.Update(). /// Will catch all new states for keyboard, mouse and the gamepad. /// internal static void Update() { #if XBOX360 // No mouse support on the XBox360 yet :( mouseDetected = false; // Copy over old mouse state mouseStateLastFrame = mouseState; #else // Handle mouse input variables mouseStateLastFrame = mouseState; mouseState = Microsoft.Xna.Framework.Input.Mouse.GetState(); // Update mouseXMovement and mouseYMovement Point lastMousePos = new Point( mouseStateLastFrame.X, mouseStateLastFrame.Y); lastMouseXMovement += mouseState.X - lastMousePos.X; lastMouseYMovement += mouseState.Y - lastMousePos.Y; mouseXMovement = lastMouseXMovement / 2.0f; mouseYMovement = lastMouseYMovement / 2.0f; lastMouseXMovement -= lastMouseXMovement / 2.0f; lastMouseYMovement -= lastMouseYMovement / 2.0f; if (mouseWasCentered && BaseGame.IsWindowActive) { mouseWasCentered = false; MousePos = new Point(BaseGame.Width / 2, BaseGame.Height / 2); mouseState = Microsoft.Xna.Framework.Input.Mouse.GetState(); } // if if (MouseLeftButtonPressed == false) startDraggingPos = MousePos; mouseWheelDelta = mouseState.ScrollWheelValue - mouseWheelValue; mouseWheelValue = mouseState.ScrollWheelValue; // Check if mouse was moved this frame if it is not detected yet. // This allows us to ignore the mouse even when it is captured // on a windows machine if just the gamepad or keyboard is used. if (mouseDetected == false)// && //always returns false: Microsoft.Xna.Framework.Input.Mouse.IsCaptured) mouseDetected = mouseState.X != mouseStateLastFrame.X || mouseState.Y != mouseStateLastFrame.Y || mouseState.LeftButton != mouseStateLastFrame.LeftButton; #endif // Handle keyboard input keysPressedLastFrame = new List(keyboardState.GetPressedKeys()); keyboardState = Microsoft.Xna.Framework.Input.Keyboard.GetState(); // And finally catch the XBox Controller input (only use 1 player here) gamePadStateLastFrame = gamePadState; gamePadState = Microsoft.Xna.Framework.Input.GamePad.GetState( PlayerIndex.One); // Try player index two if (gamePadState.IsConnected == false) gamePadState = Microsoft.Xna.Framework.Input.GamePad.GetState( PlayerIndex.Two); // Handle rumbeling if (leftRumble > 0 || rightRumble > 0) { if (leftRumble > 0) leftRumble -= 0.85f * BaseGame.MoveFactorPerSecond; if (rightRumble > 0) rightRumble -= 0.85f * BaseGame.MoveFactorPerSecond; if (leftRumble < 0) leftRumble = 0; if (rightRumble < 0) rightRumble = 0; Microsoft.Xna.Framework.Input.GamePad.SetVibration( PlayerIndex.One, leftRumble, rightRumble); } // if (leftRumble) } // Update() #endregion #region Unit testing #if DEBUG public static void TestXboxControllerInput() { TestGame.Start( delegate { if (Input.GamePadAJustPressed) Input.GamePadRumble(0.35f, 0.475f); else if (Input.GamePadBJustPressed) Input.GamePadRumble(0.85f, 0.95f); TextureFont.WriteText(30, 60, "Press A for a little gamepad rumble"+ "and B for heavy gamepad rumble effect"); }); } // TestXboxControllerInput() #endif #endregion } // class Input } // namespace XnaShooter.Helpers