7
\$\begingroup\$

I have following idea about processing keyboard input. We capture input in "main" Game class like this:

protected override void Update(GameTime gameTime)
{
    this.CurrentKeyboardState = Keyboard.GetState();

    // main :Game class logic here

    base.Update(gameTime);

    this.PreviousKeyboardState = this.CurrentKeyboardState;
}

then, reuse keyboard states (which have internal scope) in all other game components. The reasons behind this are 1) minimize keyboard processing load, and 2) reduce "pollution" of all other classes with similar keyboard state variables.

Since I'm quite a noob in both game and XNA development, I would like to know if all of this sounds reasonable.

UPDATE: If someone is interested, actual utility class, as suggested by David Gouveia, I've created can be found here.

\$\endgroup\$

1 Answer 1

12
\$\begingroup\$

Yes it's perfectly reasonable, and I could leave it at that!

... but personally I prefer having a bit more encapsulation. So instead of managing the state inside the Game class and providing global access to it, I prefer wrapping it in its own class instead.

Here's an example from memory. Not sure if I missed some detail but what's important is the general idea:

public static class InputManager
{
    public static void Update()
    {
        _previousKeyboardState = _currentKeyboardState;
        _currentKeyboardState = Keyboard.GetState();
    }

    public static bool IsKeyDown(Keys key) 
    {
        return _currentKeyboardState.IsKeyDown(key);
    }

    public static bool IsKeyUp(Keys key)
    {
        return _currentKeyboardState.IsKeyUp(key);
    }

    public static bool OnKeyDown(Keys key)
    {
        return _currentKeyboardState.IsKeyDown(key) && _previousKeyboardState.IsKeyUp(key);
    }

    public static bool OnKeyUp(Keys key)
    {
        return _currentKeyboardState.IsKeyUp(key) && _previousKeyboardState.IsKeyDown(key);
    }

    private static KeyboardState _currentKeyboardState;
    private static KeyboardState _previousKeyboardState;
}

Then at the top of Game.Update I simply call Update on the manager:

InputManager.Update();

And finally everywhere else on the game I can use the wrapper directly:

if(InputManager.OnKeyDown(Keys.Space))
{
    // Shoot once
}

Some advantages:

  • Like in your solution, there's only one place in the application that needs to manage the current and previous keyboard states.
  • But instead of polluting the game class with keyboard processing, it's encapsulated in its own class just for that.
  • The class is static making it globally accessible, so that if you don't want you don't need to provide global access to your game class.
  • It's also easily reusable - if you start a new project, you can just drop that class in and you're good to go.
\$\endgroup\$
4
  • \$\begingroup\$ While you're at it, make the API easy to record and play back. This way you can use canned inputs for testing purposes later. \$\endgroup\$ Commented Apr 2, 2012 at 7:39
  • \$\begingroup\$ @PatrickHughes could you please elaborate a little on your comment? What kind of approaches can I take for this? Some links could be useful. \$\endgroup\$
    – pabdulin
    Commented Apr 2, 2012 at 8:48
  • 2
    \$\begingroup\$ @PetrAbdulin You would want to keep a list of KeyboardState objects associated with timestamps in a struct. As you play your game for testing, grab the gameTime.TotalGameTime each frame and put it in a struct with the _currentKeyboardState and on game quit write that list of KeyboardStates and TimeSpan.Milliseconds ints to disk. Then when you run the game in test-input mode, read the KeyboardStates and ints from this file and read them from the list checking that the next KeyboardState's associated timestamp matches the current gameTime.TotalGameTime.Milliseconds property. \$\endgroup\$ Commented Apr 3, 2012 at 4:39
  • \$\begingroup\$ @michael.bartnett thank you very much for detailed explanation. This all makes sense. \$\endgroup\$
    – pabdulin
    Commented Apr 3, 2012 at 4:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .