I'm using a simple InputManager class for an XNA game with keyboardState and lastKeyboardState that gets updated and has KeyDown/KeyReleased/KeyPressed functions... but ran into a small problem:
I have the 'Enter' key being used to select a tile on the map, which brings up a menu to build something on that tile... but once the menu is up, then it's updating to check whether the Enter key has been pressed to select a menu option. So the logic ends up something like this: IsKeyPressed(Keys.Enter) is true -> Open Menu -> IsKeyPressed(Keys.Enter) still true -> Menu Option 1 selected. Obviously, I don't want the game to automatically select whatever the first menu option is. Sooo, I thought maybe I could just 'flush' the old KeyboardState for one frame after IsKeyPressed so it can't still be true when the menu pops up... but apparently a KeyboardState isn't nullable.
Any ideas as to how I could flush the lastKeyboardState?
Here's the class:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace Your_Quest.GameEngine
{
public class InputManager : Microsoft.Xna.Framework.GameComponent
{
#region Variables
static KeyboardState keyboardState;
static KeyboardState lastKeyboardState;
static GamePadState[] gamePadStates;
static GamePadState[] lastGamePadStates;
#endregion
#region Properties
public static KeyboardState KeyboardState
{
get { return keyboardState; }
}
public static KeyboardState LastKeyboardState
{
get { return lastKeyboardState; }
}
public static GamePadState[] GamePadStates
{
get { return gamePadStates; }
}
public static GamePadState[] LastGamePadStates
{
get { return lastGamePadStates; }
}
#endregion
#region Constructor
public InputManager(Game game) : base(game)
{
keyboardState = Keyboard.GetState();
gamePadStates = new GamePadState[Enum.GetValues(typeof(PlayerIndex)).Length];
foreach (PlayerIndex index in Enum.GetValues(typeof(PlayerIndex)))
{
gamePadStates[(int)index] = GamePad.GetState(index);
}
}
#endregion
#region Methods
public static void Update()
{
lastKeyboardState = keyboardState;
keyboardState = Keyboard.GetState();
lastGamePadStates = (GamePadState[])gamePadStates.Clone();
foreach (PlayerIndex index in Enum.GetValues(typeof(PlayerIndex)))
gamePadStates[(int)index] = GamePad.GetState(index);
}
public static bool KeyReleased(Keys key)
{
return keyboardState.IsKeyUp(key) && lastKeyboardState.IsKeyDown(key);
}
public static bool KeyPressed(Keys key)
{
return keyboardState.IsKeyDown(key) && lastKeyboardState.IsKeyUp(key);
}
public static bool KeyDown(Keys key)
{
return keyboardState.IsKeyDown(key);
}
public static bool ButtonReleased(Buttons button, PlayerIndex index)
{
return gamePadStates[(int)index].IsButtonUp(button) && lastGamePadStates[(int)index].IsButtonDown(button);
}
public static bool ButtonPressed(Buttons button, PlayerIndex index)
{
return gamePadStates[(int)index].IsButtonDown(button) && lastGamePadStates[(int)index].IsButtonUp(button);
}
public static bool ButtonDown(Buttons button, PlayerIndex index)
{
return gamePadStates[(int)index].IsButtonDown(button);
}
private static void Flush()
{
}
#endregion
}
}
Note: Ideally, I'd like to be able to just use KeyPressed 90% of the time without it always being true that the key has been pressed a moment afterward, and I have a TimeManager class that keeps track of the individual frames where I could do a simple InputManager.Flush() every other frame if I knew some way of actually 'removing' the current state of the lastKeyboardState.