   rawinput: key combos [solved]
  Hello, I am new to the forums, and was hoping to get a bit of help.Currently I am trying to design movement for my sprite using a keyboard (rawinput).The largest issue I am facing is dealing with keeping a key held down after a combo of other keys have been pressed and released.Example:I am going to press DOWN and hold itNext I will press RIGHT and hold it, while still holding DOWN downNext I will release RIGHTThis still leaving DOWN pressed down.What ends up happening is, my sprite will move downthen he will move diagonally down to the rightthen he abruptly stops, despite still holding down DOWN.why does WM_INPUT not receive any more messages, when i still have DOWN pressed down?Here is what I have:LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_PAINT:sprite.update(hwnd);break;case WM_INPUT:{// Determine how big the buffer should beUINT bufferSize;GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof (RAWINPUTHEADER));// Create a buffer of the correct size - but see note belowBYTE *buffer=new BYTE[bufferSize];// Call the function again, this time with the buffer to get the dataGetRawInputData((HRAWINPUT)lParam, RID_INPUT, (LPVOID)buffer, &bufferSize, sizeof (RAWINPUTHEADER));RAWINPUT *raw = (RAWINPUT*) buffer;if (raw->header.dwType == RIM_TYPEKEYBOARD){// Get key value from the keyboard member (of type RAWKEYBOARD)USHORT keyCode=raw->data.keyboard.VKey;//record which keys are pressed downif(!(raw->data.keyboard.Flags & RI_KEY_BREAK)){if(keyCode==VK_UP)up=true;if(keyCode==VK_DOWN)down=true;if(keyCode==VK_LEFT)left=true;if(keyCode==VK_RIGHT)right=true;}//record which key gets releasedif(raw->data.keyboard.Flags & RI_KEY_BREAK){if(keyCode==VK_UP)up=false;if(keyCode==VK_DOWN)down=false;if(keyCode==VK_LEFT)left=false;if(keyCode==VK_RIGHT)right=false;}}//movementif(up) sprite.up(hwnd);if(down) sprite.down(hwnd);if(right) sprite.right(hwnd);if(left) sprite.left(hwnd);InvalidateRect(hwnd,NULL,TRUE);break;}case WM_CLOSE:RestoreDelay();DestroyWindow(hwnd);break;case WM_DESTROY:RestoreDelay();PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;}Note: sprite.update(hwnd) --> redraws the screenup,down,left,right are global static bool variablessome of the attempts I tried included:storing the wParam, and lParam values for the first key pressed down, then when the msg did not equal WM_PAINT, or WM_INPUT, i set lParam and wParam to the stored values, and set msg to WM_PAINT. This was in an if statement before the switch. All that did was cause the program to crash.The other attempt I tried was to place some of the sprite movements into the default switch statement as well. Then I would call InvalidateRect() if any of the keys were still pressed down (in that check within the default). All this resulted in was the sprite to move incredibly fast all the way across the window.I searched through the forum and foundhttp://www.gamedev.net/community/forums/topic.asp?topic_id=564109I also was reading fromhttp://www.toymaker.info/I would greatly appreciate any help!Thanks[Edited by - flaber on May 18, 2010 4:47:20 PM]
Quote:why does WM_INPUT not receive any more messages, when i still have DOWN pressed down?What do you mean by this? I think it should only receive three messages, DOWN Pressed, RIGHT Pressed, RIGHT released. What more messages do you expect it to receive?I think you need to familiarize yourself with some features of your debugger here. At a quick glance I don't see anything wrong (though I don't really know what this struct looks like "raw->data.keyboard.Flags".I might suggest you put a watch on variable "down" so that your debugger will break whenever the value changes from true to false. Then you should be able to see what is causing it to become false without releasing the down button. If you are using it as a global variable you could be accidentally changing it anywhere.   ;  The reason why I thought there should be more WM_INPUTs, is to recognize that a key is held down.The only place that I change the sprite coordinates is within the WM_INPUTs case.When I first initially hold down the DOWN arrow, I'm assuming WM_INPUTs are continually being sent, as my sprite is continuously moving downward. Then when I press the RIGHT arrow and hold it down, I'm assuming WM_INPUTs are being sent for the RIGHT arrow key being held down. (The sprite moves diagonally down to the right, as DOWN is still true). When I release the RIGHT arrow key, it appears that there are no more WM_INPUTs being sent, as the sprite is no longer moving. The true and false values for the up,down,left,right variables are correct. I took extra care to double check all the values to be correct. Also, the only place I use those are within the WM_INPUT case.I placed a messagebox to test if releasing the DOWN key would be recognized://record which key gets releasedif(raw->data.keyboard.Flags & RI_KEY_BREAK){if(keyCode==VK_UP)up=false;if(keyCode==VK_DOWN){down=false;MessageBox(hwnd,"down released","test",MB_OK);}if(keyCode==VK_LEFT)left=false;if(keyCode==VK_RIGHT)right=false;}If I release the DOWN key after the above mentioned combo, the system recognizes the release of the DOWN arrow key and creates the message box.If the system recognizes when the DOWN arrow key is released, even after using the RIGHT arrow key, why can I not get it to recognize that the DOWN arrow key is still pressed down (after releasing RIGHT, and before releasing DOWN).I want the sprite to move downward, then diagonally down and to the right, then down again without ever lifting my finger from the DOWN arrow key.I have it moving downward, then diagonally down and to the right, then it stops.Hopefully this was a little more clear.NOTE:the 'raw->data.keyboard.Flags' is a flag to recognize if a key is down or released.According to:http://www.toymaker.info/Games/html/raw_input.htmlThanks again for the help,I appreciate!   ;  There's nothing odd about this. Open up Notepad, press and hold "a", and watch a line of "aaaaa" start across the screen. While still holding "a", hold "z" as well; now z's start scrolling. Let up "z" while "a" is still held down -- nothing more is typed. This is just how key repeat works.In your game, you should not be relying on key repeat for motion. In fact, you should be more or less ignoring subsequent WM_KEYDOWNs. Just record whether the important keys are currently pressed or not, and move based on those states.   ;Quote:nothing more is typed. This is just how key repeat works.Oh okay! That's what I figured, I wasn't sure if it was possible or not to resort back.Taking your advice about not listening to WM_KEYDOWNs for movement as much, I think I found an alright solution for myself.I removed the movement out of WM_INPUT, created a new function for movement, and created a timer. I then would call on the movement() with the WM_TIMER. Not necessarily sure if this is the best solution, but it's working well enough for my experimenting / learning.Id say this thread is now wrapped up/solved!Thanks again for the clarifications,now Im back to experimenting and learning!;  If you need WM_TIMER, I'm gonna guess that you're using GetMessage instead of PeekMessage in your main game loop. Take a look here.   