I am trying to create a snake game in C using the ncurses library. I would like my program to detect user input at a constant tick speed. If there is no input after a certain amount of time I would like my program to continue along (ie. update game).
This is what I wrote to test out the halfdelay(i) function:
#include <ncurses.h>
int main(void)
{
initscr();
halfdelay(5);
int user_input;
do
{
user_input = getch();
if (user_input != -1)
{
clear();
printw("Key pressed: %d\n", user_input);
}
else
{
//printf("Timeout.\n");
printw("Timeout.\n");
}
} while (user_input != ESC);
endwin();
return 0;
}
EDIT #1:
I would like to see
Timeout.
Timeout.
Timeout.
Code used:
#include <ncurses.h>
int main(void)
{
initscr();
halfdelay(5);
int in;
do
{
timeout(1);
in = getch();
if (in != -1)
{
clear();
printw("Key pressed: %d\n", in);
}
else
{
//printf("Timeout.\n");
printw("Timeout.\n");
}
refresh();
} while (in != 27);
endwin();
return 0;
}
Some history first.
Traditionally, the ESC key value has been used as the prefix for escape sequences, which denote special sequences of characters that can be interpreted as a non-graphic character (e.g., an arrow key, a function key, etc.)
Due to (n)curses focus on portability (and telecommunication), out of the box it supports this notion of escape sequences, and as such pressing the ESC key can have some side effects. Notably, when keypad
is enabled, there is an inbuilt delay as the program waits to decide if the user simply pressed ESC or if it needs to wait for some more information to complete the escape sequence. This timing can be adjusted via the ESCDELAY
environment variable, or the set_escdelay
function.
All this is important as you work forward, as given its a game you may want to enable the functionality of the keypad
eventually, which will create some extra steps when using the ESC key.
And because of all this, there is no ESC
or KEY_ESC
macro for for the escape key. Instead, its raw code is 27
(or the octal 033
).
Your use of the halfdelay
function seems perfectly fine to me, just know that the argument is in tenths of a second, so 5
is half a second. Tenths of a second may not achieve the desired effect in a game, so consider using the timeout
function instead, which allows for higher precision.
A simple, working example:
#include <ncurses.h>
int main(void) {
initscr();
halfdelay(5);
int user_input;
while ((user_input = getch()) != 27) {
clear();
if (user_input == ERR)
printw("Timeout.");
else
printw("Key pressed: %d\n", user_input);
refresh();
}
endwin();
}
Your updated program "works", it just doesn't clear the screen properly. Note that you probably don't want to mix calls to printw
and printf
as it creates a strange mess of the screen.
Also, you should use halfdelay
or timeout
, but not both. Remember that timeout
takes its argument in milliseconds, which is 1/1000 of a second, and it sets the blocking delay for a window (timeout
for stdscr
, wtimeout
for specific windows). It's not a "sleep" style function.
Use one delay function at a time, move clear
to outside the if
statement, and use printw
. This is functionally the same program to the one posted above, just with a do ... while
loop.
#include <ncurses.h>
int main(void) {
initscr();
/*
noecho();
scrollok(stdscr, TRUE);
*/
timeout(500);
int in;
do {
in = getch();
clear();
if (in != ERR)
printw("Key pressed: %d\n", in);
else
printw("Timeout.\n");
refresh();
} while (in != 27);
endwin();
}
If you are expecting the display of this program to be something along the lines of
Timeout.
Timeout.
Key pressed: 65
Timeout.
...
like a more traditional terminal, then you simply want to remove clear
all together, and un-comment noecho
and scrollok
.