I have a problem that I think is caused by the wm_keyup message not being sent correctly. I believe that the same problem occurs in Minecraft when you move your character and the input will get 'stuck'. The action of the key continues after you pressed it and doesn't cease until you tap the key again. I heard that it could be an issue between windows and the keyboard but I'm not completely sure. Also, most other mainstream games don't have this problem so there must be a correct way to do it. This is what my windows procedure code looks like:
case WM_KEYDOWN:
for (list<KeyInput>::iterator t = key_inputs.begin(); t != key_inputs.end(); ++t)
(*t).PushKeyDown(ConvertKeyCode(wparam));
return 0;
case WM_KEYUP:
for (list<KeyInput>::iterator t = key_inputs.begin(); t != key_inputs.end(); ++t)
(*t).PushKeyUp(ConvertKeyCode(wparam));
return 0;
Each KeyInput object has a queue that gets filled with key inputs and is emptied as keyboard input is requested. This code is for a multithreaded game and this technique ensures that no input is missed on any thread. I am using mutual exclusion in the KeyInput objects.
I get this problem more in my game than in Minecraft and I have no idea why. I also got it before when I was doing simpler, non-multithreaded code. I don't know how to fix this.
I appreciate any help or suggestions anyone has to offer.
After looking at the documentation for the WM_KEYDOWN message I found out that the 31st bit of lparam tells whether or not the last keydown message was the same as the latest. If you use this info to ignore repeat messages, you can get rid of the problem (but you lose repeat input from the key when it is held down). Here is my code:
case WM_KEYDOWN:
{
union
{
uint lparam;
struct { uint bits:30,_30:1,_31:1; };
} lparam_data;
lparam_data.lparam = lparam;
if (!lparam_data._30)
// key was pushed
return 0;
}
Related
I'm working on a little project to improve my coding skills and I have a problem. I'm doing a console version of Flappy Bird. So i have a map which is a two-dimensional array of chars and this map have to move to the left. I am moving all elements of an array one place to the left and after that, clearing console and showing moved map. And here is problem, map has to move constantly but player have to control a bird while map is moving. I wanted to use _getch() but it pausing a program. A question is: Can i read a keyboard input without pausing program? I mean that the map will still moving and when i press for example Space in any moment the bird position will change. I'm working on Windows 10
Even if beginners hope it to be a simple operation, inputting a single character from the keyboard is not, because in current Operating Systems, the keyboard is by default line oriented.
And peeking the keyboard (without pausing the program) is even harder. In a Windows console application, you can try to use functions from user32, for example GetAsyncKeyState if you only need to read few possible keys: you will know if the key is currently pressed and whether if was pressed since the last call to GetAsyncKeyState.
But beware: these are rather advanced system calls and I strongly advise you not to go that way if you want to improve your coding skills. IMHO you'd better learn how to code Windows GUI applications first because you will get an event loop, and peeking for events is far more common and can be used in real world applications. While I have never seen a real world console application trying to peek the keyboard. Caveat emptor...
Including conio.h
you can use this method:
#define ARROW_UP 72
#define ARROW_DOWN 80
#define ARROW_LEFT 75
#define ARROW_RIGHT 77
int main(){
int key;
while( true ){
if( _kbhit() ){ // If key is typed
key = _getch(); // Key variable get the ASCII code from _getch()
switch( key ){
case ARROW_UP:
//code her...
break;
case ARROW_DOWN:
//code her...
break;
case ARROW_LEFT:
//code her...
break;
case ARROW_RIGHT:
//code her...
break;
default:
//code her...
break;
}
}
}
return 0;
}
The upper code is an example, you can do this for any key of keyboard. In this sites you can find the ASCII code of keys:
http://www.jimprice.com/jim-asc.shtml#keycodes
https://brebru.com/asciicodes.html
Say me if it has help you!
Lets start with what my code looks like then I will explain my problem:
int main {
char ch; //Stores key presses
initscr();
raw();
nonl();
keypad(stdscr, TRUE);
noecho();
//Some code
ch = getch();
switch (ch) {
case KEY_UP:{
//Code that works
break;
}
case KEY_ENTER:{
//Some code- that doesn't work problem being the above
break;
}
//Other case statements
}
Now the problem:
The problem I run into if you haven't already worked it out is that when ever I press the enter/return key on my keyboard absolutely nothing happens.
I have tried changing the KEY_ENTER to '\n' - didn't work - even changed the char ch which when through multiple iterations including int and wchar_t.
All to no avail, and before you say search for answers and send me packing my bags to go onto a perilous adventure through every corner of the interwebs, I have already tried that, if I hadn't I wouldn't have ventured here, in search of aid.
So now my search has brought me here and I ask of you - the lovely people of the interwebs - to help me in my search of the answer I have been looking for
And to who ever may be valiant enough to answer it I give you my up most gratitude and thanks
Try case '\r':. (For good measure, you could do case '\r': case '\n': case KEY_ENTER:, as is basically done in testcurs.c, to capture all possibilities.) The call to nonl() is why you're getting '\r' instead of '\n'.
As for KEY_ENTER, my only excuse is that it's marked "not reliable" in the PDCurses comments. I could pretend that it's meant to represent the keypad's "Enter" key, rather than the key usually marked "Return" in the main part of the keyboard... except that PDCurses also has PADENTER, specifically for that purpose. In truth, like a lot of things in PDCurses, the reason KEY_ENTER is there, and defined the way it is, is a bit of a historical mess.
the message queue is present in any type of program or Unix is present only in programs written in Windows interface?
For example this programm:
int main()
{
short int n;
while(1)
{
if (n = GetKeyState(VK_UP))
{
cout << n;
}
else
{
cout << n;
}
Sleep(150);
}
return 0;
}
have or not the message queue? If yes, the GetKeyState function retrieves the keyboard messages from the message queue?
Yes, you must call PeekMessage or GetMessage to make GetKeyState return new values, for further reading look here:
http://blogs.msdn.com/b/oldnewthing/archive/2004/11/30/272262.aspx
and here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646301%28v=vs.85%29.aspx
If you dont want message loop use GetAsyncKeyState.
GetKeyState is a Windows function that interacts closely with the Windows message queue. The function does not exist in Unix.
As I explained in your previous question, GetKeyState provides information about the key state associated with the most recently retrieved message. Since your console application does not have a message queue, and is not pumping messages, GetKeyState yields no useful information.
Again, as explained in your previous question, you use GetAsyncKeyState to obtain information about the state at the instant that the API call is made.
Finally, again repeating statements from your earlier question, test for a key being pressed by checking for a negative return value. For instance:
if (GetAsyncKeyState(VK_UP) < 0)
....
My most important advice to you is that when you ask a question here on Stack Overflow, you read the answers! If you don't understand them, leave comments asking for clarification.
I am making Pacman in C++ with the Ncurses library. I am able to move Pacman with my code, but I want to move it so that pacman keeps moving even when I am not pressing any key and when I press another direction key, it changes direction. Right now, the pacman only takes one step when I press a key. Also I have to press a key 2 or 3 times before pacman moves in that direction.
if (ch==KEY_LEFT)
{
int b,row,column;
getyx(stdscr,row,column);
int h;
do // do-whileloop to move the pacman left until it hits the wall
{
column-=1;
mvprintw(row,column,">"); //print the ">" symbol
refresh();
waitf(0.1); //this pauses the game for 0.1sec
attron(COLOR_PAIR(1));
mvprintw(row,column,">");
attroff(COLOR_PAIR(1));
refresh();
waitf(0.1);
mvprintw(row,(b),"O"); //showing the open mouth of pacman
refresh();
waitf(0.1);
attron(COLOR_PAIR(1));a
mvprintw(row,column,"O");
attroff(COLOR_PAIR(1));
h = getch();
}
while(h == KEY_LEFT);
}
right = getch();
loop to move right in an if condition
up = getch();
loop to move up in an if condition
down = getch();
oop for moving down in an if condition.
The standard solution to this is the finite-state machine. The character has six or so possible states: standing, moving up, moving right, moving down, moving left, dead. Rather than a keypress directly moving the character, the keypress should change the character's state.
In such a small application, rather than implementing an incredibly flexible finite-state machine, you may use a very simple implementation as such:
enum PlayerState {
Standing,
MovingUp,
MovingRight,
MovingDown,
MovingLeft,
Dead
};
Then, inside your game loop you can add a very simple state check which then takes the appropriate action for the frame.
switch(state) {
case Standing:
break;
case MovingUp:
player.PositionY += 1;
break;
// ...
}
The last step is to hook input, which depends on your method of retrieving input. Using callbacks, an example is:
void KeyDown(Key k) {
switch(k) {
case UpArrow:
if(state != Dead)
state = MovingUp;
break;
case RightArrow:
if(state != Dead)
state = MovingRight;
// ...
}
}
You can see why in a larger project it would be important to implement a more flexible finite-state machine, but hopefully this example has given you an easy-to-understand idea.
You need an equivalent of kbhit, ie. a non-blocking getch. Which really gives the solution, set O_NONBLOCK on the input. See an example here. Once you have this, simply loop contiguously and just check for the key hit, w/o waiting on actual key press.
Function getch is blocked until some key is pressed. If you don't want to be blocked then call _kbhit before getch too make sure that there is something in input buffer.
EDIT: Take a look at ncurses functions nodelay and cbreak. They enable asynchronous input.
I suggest you take a look at the model-view-controller model, it will help you with this problems and all the other problems that you will have if you continue your program like this.
Edit: shortcut
To move your pacman continuously you will need a separate thread to control it and make it move. Take a look at pthreads for that.
If you keep only the user input in the main run loop of your program, the problem that you have to press the keys a few times will go away too (the problem here is that the processor has to be on the getch() line when you press the key, otherwise it will not be detected.
It is pretty easy
for each direction make 4 function
and inside the function,put in the other 3 direction function which get activated by kbhit.
and put a else statement in which it keeps moving forward if you do not hit a button i.e (!kbhit());
and then put all this in a loop.
If you do this for all the direction functions you should be able to get the desirable outcome.
I don't know how to write a good question here, but, basically, does anyone know where I can possibly find some C++ source code using these to actually set keyboard state? For some reason using it the way MSDN does on Windows 7 doesn't do...anything at all.
Basic code:
PBYTE keyState;
GetKeyboardState(keyState);
...
// Later on when I need to set the keyboard state (key pressed etc) back to original:
SetKeyboardState(keyState);
and ... nothing happens :(
From:
http://www.gamedev.net/community/forums/topic.asp?topic_id=43463
First off, GetKeyboardState() would be the wrong function to use because as Windows has a chance to process keyboard messages (whether you want it too or not) it updates the results of the keyboard's state for the next call to GetKeyboardState().
Here's a little function that I use to get the status of the keyboard's keys. Be carefull though, depending on how fast your main loop is, it may cause problems if you aren't expecting it.
You need to keep track of whether or not a specific key was pressed the last time you called the ReadKeyboard() function. If your loop polls the keyboard 30 times a second, then pressing a key once probably causes the key to be flagged 3 or 4 calls in a row. Rather confusing sometimes. Just thought I'd mention it.
void ReadKeyboard( char* keys )
{
for (int x = 0; x < 256; x++)
keys[x] = (char) (GetAsyncKeyState(x) >> 8);
}