Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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.

share|improve this question
add comment

1 Answer 1

up vote 12 down vote accepted

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.
share|improve this answer
    
Thank you! Your solution is indeed much better. –  Petr Abdulin Apr 2 '12 at 6:04
    
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. –  Patrick Hughes Apr 2 '12 at 7:39
    
@PatrickHughes could you please elaborate a little on your comment? What kind of approaches can I take for this? Some links could be useful. –  Petr Abdulin Apr 2 '12 at 8:48
    
Thanks, yet another super useful response. :) –  Brett Chalupa Apr 2 '12 at 14:28
2  
@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. –  michael.bartnett Apr 3 '12 at 4:39
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.