I wanted to get familiar with the curses interface (never used it before), so I wrote a little snake game last weekend. There's a one-line status WINDOW * and the rest of the screen is the field WINDOW * The game logic calls a central drawing function to put an item, only when necessary:
/* note: CP_* are just enum values to give my own color pairs names */
void
screen_putItem(Screen *self, int y, int x, Item item, int refresh)
{
switch (item)
{
case EMPTY:
mvwaddch(self->field, y, x, ' '|COLOR_PAIR(CP_WHITE));
break;
case HEAD:
#ifdef WIN32
/* 'smiley' character for windows console */
mvwaddch(self->field, y, x,
1|COLOR_PAIR(CP_YELLOW)|A_BOLD|A_ALTCHARSET);
#else
mvwaddch(self->field, y, x, '@'|COLOR_PAIR(CP_YELLOW)|A_BOLD);
#endif
break;
case TAIL:
mvwaddch(self->field, y, x, ACS_CKBOARD|COLOR_PAIR(CP_YELLOW));
break;
case FOOD:
mvwaddch(self->field, y, x, '#'|COLOR_PAIR(CP_GREEN)|A_BOLD);
break;
case FFOOD:
mvwaddch(self->field, y, x, '#'|COLOR_PAIR(CP_GREEN));
break;
case WALL:
mvwaddch(self->field, y, x,
' '|COLOR_PAIR(CP_RED)|A_REVERSE);
break;
}
if (refresh) wrefresh(self->field);
}
Problem is: in rxvt, the body of the snake (made from TAIL items) is sometimes flickering. It is not redrawn on snake movement, only the last position of the head is replaced by a TAIL and the tail item at the end of the snake is replaced by an EMPTY.
For your reference, the whole project is on github, see the revision at time of asking this question.
For input, the code uses getch() and I already checked this isn't the problem (it shouldn't be, stdscr is refreshed at init and never touched again) by using only wgetch() on the field window with the same result.
Also, it works fine (flicker-free) in good old xterm and in the windows console, using pdcurses. It works fine in rxvt iff I replace the ACS_CKBOARD in the snippet above with some "ordinary" character.
So, now I'd like to know: Did I encounter a bug/shortcoming in rxvt? Is there something special about the ACS_* characters that could cause a terminal to flicker? Is there anything just wrong with my approach?
Tracing shows me that your program does almost all wgetch's from stdscr, but almost all refresh's are done against the second window created (looks like the first is just a status line).
ncurses' trace feature is normally in a debug-library; the copies that I compile for myself have it compiled in normally.