6
votes

I'm trying to implement keyboard text input for chatting in game, typing character name, save file name, etc.

I was messing around with KeyboardState trying to get the newest added symbol to translate in into character that I could add to my input string, but it seems to sort the array of currently pressed keys in some order (I bet it's sorted by keycode), so I can't easily find which key was pressed last to add it to input string.

Is there an easy way to detect the last pressed text key (including situations when multiple keys are pressed, because people do that sometimes), or is it easier to make use of some existing solutions?

I'm studying C# and XNA, so I'd like to be able to do it myself, but in the end I want my game to work.

2

2 Answers

6
votes

In order to handle text input, you'll need to know when a key is pressed or released. Unfortunately, the XNA's KeyboardState doesn't really help with this, so you have to do it yourself. Basically, you just need to compare the current update's PressedKeys with the PressedKeys from the previous update.

public class KbHandler
{
    private Keys[] lastPressedKeys;

    public KbHandler()
    {
        lastPressedKeys = new Keys[0];
    }

    public void Update()
    {
        KeyboardState kbState = Keyboard.GetState();
        Keys[] pressedKeys = kbState.GetPressedKeys();

        //check if any of the previous update's keys are no longer pressed
        foreach (Keys key in lastPressedKeys)
        {
            if (!pressedKeys.Contains(key))
                OnKeyUp(key);
        }

        //check if the currently pressed keys were already pressed
        foreach (Keys key in pressedKeys)
        {
            if (!lastPressedKeys.Contains(key))
                OnKeyDown(key);
        }

        //save the currently pressed keys so we can compare on the next update
        lastPressedKeys = pressedKeys;
    }

    private void OnKeyDown(Keys key)
    {           
        //do stuff
    }

    private void OnKeyUp(Keys key)
    {
        //do stuff
    }
}

Give your Game class a KbHandler, and call it's Update method from your Game's update method.

(BTW there is probably a more efficient way to compare two arrays than with foreach and Contains, but with so few items to compare I doubt it will matter.)

0
votes

You could try the example listed here

KeyboardState keybState = Keyboard.GetState();
if (keybState.IsKeyDown(Keys.Left)) {
  // process left key
}
if (keybState.IsKeyDown(Keys.Right)) {
  // process right key
}

This will handle multiple keys pressed at the same time. If you want to avoid that, add an else before the second if (and following ones)

Also, a key held down will fire multiple key-down events -- if this is not desired, you will need to introduce a state variable that you flip when the key is down and when it is not and proceed according to its state when the key is pressed