Multiple Key Presses in XNA?

I'm actually trying to do something fairly simple.

I cannot get multiple key presses to work in XNA. I've tried the following pieces of code.

else if (keyboardState.IsKeyDown(Keys.Down) && (keyboardState.IsKeyDown(Keys.Left)))
{
//Move Character South-West
}


and I tried.

else if (keyboardState.IsKeyDown(Keys.Down))
{
if (keyboardState.IsKeyDown(Keys.Left))
{
//Move Character South-West
}
}


Neither worked for me. Single presses work just fine. Any thoughts?

• How do the values of both keydown checks look like if you debug it (or look at the GetPressedKeys structure of the keyboardState)? How do the entire method look like? Dec 25 '10 at 0:11

Use GetPressedKeys() to get all of the currently pressed keys and iterate through them doing what you want.

If you're moving the player or something, create an initial Vector3 at the beginning and add modifier values to it and add it to the player position after the input checking has completed.

Something like this:

Vector3 positionToAdd = Vector3.Zero;
Keys[] currentPressedKeys = currentKeyboardState.GetPressedKeys();
foreach( Keys key in currentPressedKeys )
{
if( key == Keys.W )
positionToAdd += Vector3( 0.0f, 1.0f, 0.0f );

if( key == Keys.S )
positionToAdd += Vector3( 0.0f, -1.0f, 0.0f );

if( key == Keys.A )
positionToAdd += Vector3( -1.0f, 0.0f, 0.0f );

if( key == Keys.D )
positionToAdd += Vector3( 1.0f, 0.0f, 0.0f );
}



Personally, I don't do this, I just use if statements WITHOUT the else to make sure program flow isn't being disrupted unintentionally.

Ray

The code in your question is fine. The problem must be in the code above it, perhaps you are doing something like this:

// ...
if (ks.IsKeyDown(Keys.Down)) { /* ... */ }
else if (ks.IsKeyDown(Keys.Down) && (ks.IsKeyDown(Keys.Left))) { /* ... */ }
// ...


In which case the first condition will trigger and the second will not (due to else).

Here is how to do 2D input using the keyboard:

Vector2 direction = Vector2.Zero;
if(ks.IsKeyDown(Keys.Up)) direction += new Vector2(0, 1);
if(ks.IsKeyDown(Keys.Down)) direction += new Vector2(0, -1);
if(ks.IsKeyDown(Keys.Left)) direction += new Vector2(-1, 0);
if(ks.IsKeyDown(Keys.Right)) direction += new Vector2(1, 0);

// Optional: make sure direction is always of unit length (prevents straferunning)
if(direction.LengthSquared() > 1f) direction.Normalize();


Personally I'd avoid using GetPressedKeys(), because it allocates memory every time you call it. Probably not enough to be a performance issues on Windows, but it will be if you ever port to Xbox 360. It exists to support "press any key" scenarios only.

• Thanks Andrew, this certainly was the problem I was having. Dec 25 '10 at 16:59

Your else if statements could be interfering with the program flow. Try restructuring your code, or setting bit flags for each key pressed. Or perhaps your keyboard doesn't support some keys simultaneosly pressed (happens to my old laptop).

• I've yet to see a keyboard where the arrow keys interfere in such a way, but I guess it could do that too ^^ Dec 25 '10 at 0:00

I had the same problem when I used the arrows keys in conjunction with the space bar on my pc. I changed the arrow keys to WASD and the problem went away.