3
\$\begingroup\$

I'm working on a Pong game and right now I'm working on being able to register multiple KeyDown presses simulatenously. I used the Win32 native method GetKeyBoardState first to loop through all of the virtual keys and see if any of the keys matched the game input keys. Now this worked just fine but in the interest of optimization I figured that it would be quicker to use GetKeyState since there are only 4 valid input keys and then simply check if any of those keys are pressed down.

Surprisingly it is incredibly slow and choppy, a lot worse than GetKeyBoardState so I'm wondering if there's something in my code that's slowing it down. Here's the complete implementation

NativeMethods.cs

internal static class NativeMethods
 {
 [DllImport("user32.dll")]
 [return: MarshalAs(UnmanagedType.Bool)]
 internal static extern bool GetKeyboardState(byte[] lpKeyState);
 [DllImport("user32.dll")]
 internal static extern short GetKeyState(int nVirtKey);
 }

Keyboard.cs

static class Keyboard
{
 public static bool GetKeyState(Keys vKey)
 {
 short results = NativeMethods.GetKeyState((int)vKey);
 // We're only going to use this to look for arrow keys so
 // No need to differntiate results based on low or high order bits
 switch (results) 
 {
 case 0: //KEY STATE: NOT PRESSED
 return false;
 case -127: //KEY STATE: PRESSED
 return true;
 }
 return false;
 }

GameForm.cs

 private void GameForm_KeyDown(object sender, KeyEventArgs e)
 {
 var movementData = new Tuple<int, Move>(-1, Pong.Move.Down);
 //Check how many keys that are pressed down (for example both players might be moving their paddles simulatenously)
 var pressedKeys = inputKeys.Where(key => Keyboard.GetKeyState(key));
 //Check if pressed key equals any of the player assigned keys.. If so call MovePaddle()
 foreach (Keys key in pressedKeys)
 {
 switch (key)
 {
 case Keys.Up:
 movementData = Tuple.Create(0, Pong.Move.Up);
 break;
 case Keys.Down:
 movementData = Tuple.Create(0, Pong.Move.Down);
 break;
 case Keys.W:
 movementData = Tuple.Create(1, Pong.Move.Up);
 break;
 case Keys.S:
 movementData = Tuple.Create(1, Pong.Move.Down);
 break;
 }
 gameController.MovePaddle(movementData.Item1, movementData.Item2);
 } 
 }
asked Apr 18, 2014 at 9:16
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Your bool GetKeyState is incorrect. The reason for this is that the comment

No need to differntiate results based on low or high order bits

is wrong. The low bit will alternate between 0 and 1 for all keys, not just caps-lock/num-lock/scroll-lock. So the method will return false for every second key-press.

Replace it by:

public static bool GetKeyState(Keys vKey)
{
 short state = NativeMethods.GetKeyState((int)vKey);
 return (state & 0x80) != 0;
}
answered Apr 20, 2014 at 19:19
\$\endgroup\$
2
\$\begingroup\$

What is impacting you performance so heavily is the creation of Tuples everytime you recieve a keypressed event.

creating objects is slow. What you should do instead is, directly apply the changes to the moving objects (your two pong-thingies).

private void GameForm_KeyDown(object sender, KeyEventArgs e)
{
 var pressedKeys = inputKeys.Where(key => Keyboard.GetKeyState(key));
 foreach(Keys key in pressedKeys)
 switch(key){
 case Keys.Up:
 leftPong.Positon += FIXEDVALUE;
 break;
 case Keys.Down:
 leftPong.Position -= FIXEDVALUE;
 break;
 //continue...
answered Apr 18, 2014 at 9:38
\$\endgroup\$
3
  • \$\begingroup\$ Are you saying that there's a big difference in performance inbetween creating one instance of an integer, one instance of an enum and create one instance of a tuple to hold aforementioned instances? I must admit I didn't think that tuples would take up a lot of resources. \$\endgroup\$ Commented Apr 18, 2014 at 9:46
  • \$\begingroup\$ @Overly It's not the creation in itself, but the interval in which it's perfomed \$\endgroup\$ Commented Apr 18, 2014 at 10:09
  • 1
    \$\begingroup\$ Sounds unlikely. Creating objects only matters if you do it millions of times per second. \$\endgroup\$ Commented Apr 20, 2014 at 19:12

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.