Debounce user input in c++ - c++

we have a project on school, coding a volleyball - match as console application.
We should make input-output for teams and score etc, and bind keys to Team1-score+1, Team2-score-1 etc. That's fine. We use getch() to bind these keys.
My problem: If you for example press R and R is Team1-score+1 and hold this key, it will continue adding the score+1, and we should stop that so you need to press R again if you want to add another point.
I didn't find this solution anywhere!
Can anyone give an example how to fix it?
I am new on coding so I am inexperienced.
Thanks for help guys!
EDIT: I am using Windows 10, important part of my code:
while (true)
{
_kbhit();
char L = _getch();
if (L == 114)
{
score1 = score1 + 1;
}
else if (L == 99)
{
score1 = score1 - 1;
}
else if (L == 117)
{
score2 = score2 + 1;
}
else if (L == 110)
{
score2 = score2 - 1;
}
else if (L == 113)
{
L=="number" is the ascii-code for buttons r,u,c,n,q

getch() operates on stdio which effectively is just a bytestream coming/going from/into the OS. It doesn't have the concept of "key presses/releases". When you keep a key pressed the OS will start to autorepeat the pressed character. To make things worse for your use case, if you keep a key pressed, and then press another key, the key repeats of the first will cease.
Now there are ways to get raw key down/up events, but these involve OS specific programming interfaces; you didn't tell us which OS you're using, so it's a bit of guesswork there. Doing what you want to do in the console is somewhat possible, but it's awkward to use. For Windows see C++ console keyboard events, for Linux see Receiving key press and key release events in Linux terminal applications?
However I strongly suggest you don't even try to implement all that OS level key event interfacing yourself, and instead make use of a cross platform library that offers a framework for doing exactly what you want to do there. One of the most widely used frameworks these days is SDL http://libsdl.org/ – it will move you out of the console though (when it comes to games: good riddance, except if you're working on a rouge-like game).

If you are using the console then most operating systems will wait a second after you press a key before registering that key press again. You can try it now: press a key on your keyboard and see what the response is.
Making sure someone doesn't accidentally press a key twice is a problem that the OS takes care of, because otherwise every application taking keyboard input would need to code their own solution to the problem.
If you want to go further than what the OS does, you can use a timer in your program with the chrono library, and wait n seconds before allowing input to be registered again.

Related

Can I get character from keyboard without pausing a program

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!

How do I make something happen on the screen even without a key being pressed?

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.

Small c++ game using graphics.h , calling multiple functions at once ? (multi threading?)

I'm writing a small ball game. I have a function called gravity and I also have a while loop that checks whether the user wants to move the ball using wsad keys.
Do I need to multi thread this or is there another way out? I cut out some of the irrelevant code for setting up the program. Here is just the stuff that matters:
while(1) {
enableGravity();
char ch = getch();// i know getch() is not going to cut it
//maybe 2 different f() multi threaded , for gravity and position,
f(ch == 'w' || ch == 'W')
updateObjPosition('U');
else if(ch == 's' || ch == 'S')
updateObjPosition('D');
else if(ch == 'a' || ch == 'A')
updateObjPosition('L');
else if(ch == 'd' || ch == 'D')
updateObjPosition('R');
}
I have these functions in main. I need the program to enable gravity and also be able to accept input to move the ball through updateObjPosition() simultaneously.
You could use multiple threads. A more obvious possibility would be a non-blocking keyboard read.
If you're doing this on Windows, you probably have a _kbhit in your standard library that will tell you if a key on the keyboard has been pressed. If you're using curses, you can use nodelay to tell getch to return immediately, whether a key has been pressed or not. Other systems may do things in different ways still, but you get the general idea...
You don't need to multi-thread. You just need an API that returns TRUE if a specified key is currently pressed down. That will likely be platform dependent. What platform are you building/running on?
For example on Win32: GetAsyncKeyState
As you have mentioned you are using old Borland compiler on TC 3.1 in the old conio.h there was a function
kbhit();
the function was a one shot solution for getting if any key is pressed on the keyboard
so here is your loop to get key input
int getKey(){
if(kbhit){
return getch();
}
return -1;
}
By they way you should upgrade to VC 08 Atleast!
For your simple project where the logic loop i guess will be quite small this will handle all the pain for you but if you write a longer application with hard logic then you will have to use better and Asynchronous methods for IO and those methods basically involve working on 2 threads 1 getting Input and the other doing logic operations ..

movement binding in c++ using ncurses

I can't get this movement binding to work. I'm using the ncurses library, update_ch and oldch are global variables. KEYERR is a macro set to -120 (I just don't handle those keypresses). I'm trying to restrict the player so he can't hold up, down, left, or right, but he has to keep pressing them to move. It's not working, you can still hold the keys down and move. Any suggestions? My logic must be off.
if(update_ch != KEYERR)
{
oldch = update_ch;
}
update_ch = getch();
if(oldch == update_ch)
{
update_ch = KEYERR;
}
I'm trying to restrict the player so
he can't hold up, down, left, or
right, but he has to keep pressing
them to move.
I am pretty sure this isn't possible with curses. If I remember correctly curses only receives characters from a terminal. It doesn't control anything about the process.
Measuring the time between to such readings might give you a hint if the user is holding a key instead of continuously pressing. I mean, when you do a reading, record the following
Key read
Time of read (millisecond precision)
When you read a value, ask the following:
Is it the same as the last key ?
What's the difference between the current time and the time of the last read ?
If it's the same key and the time difference is smaller than some threshold you can decide he's holding the key down.

Using SetKeyboardState along with GetKeyboardState in C++

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);
}