I am writing a snake game in C using the ncurses
library, where the screen updates itself every second. As those who have played the game will know, if the user enters various keys or holds down a key for long, there should be no 'buffered' key presses which get stored. In other words, if I hold down w
(the up key) and stdin
receives a sequence of 20 w
s, and subsequently enter a d
(the right key), I expect the snake to immediately move to the right, and ignore the buffered w
s.
I am trying to achieve this using the ncurses
function getch()
, but for some reason I am achieving the undesired effect which I have just described; namely that any long key presses are being stored and processed first, before considering the last key pressed, as this MWE will illustrate:
#include <stdio.h>
#include <unistd.h>
#include <ncurses.h>
int main(){
char c = 'a';
initscr();
cbreak();
noecho();
for(;;){
fflush(stdin);
timeout(500);
c = getch();
sleep(1);
printw("%c", c);
}
return 0;
}
Is there any way I can modify this code so that getch()
ignores any buffered text? The fflush()
right before doesn't seem to be helping.
I've done some more research and found out that:
This solved my problem.
Source: https://linux.die.net/man/3/flushinp
the following proposed code shows how to ignore all but the last key entered.
First the answer to your immediate question: Even when you read from
stdin
one character at a time, you normally don't want to miss one. Ifgetch()
would just return whatever character was entered last, input routines usinggetch()
would become very unreliable.Even in a snake game, you DO want to get all the characters entered. Imagine the snake moves to the right and the player wants to do a "u-turn" by hitting down and then immediately left. If your game would only pick up the last character, the snake would go directly to the left and thus kill itself. Quite a frustrating game experience ;)
The solution to your problem is simple: make your game loop poll for input much more often than the snake is moved and maintain a queue of requested direction changes. I've done that in my curses-based snake game.
Here is the relevant code from the game loop:
And here is how the snake implements and uses the queue:
Good luck with your game!