I'm trying to write a program like nethack with ncurses. The program works fine, draws me a box and everything perfectly while not eating up much of my CPU. After I added the while(true)
loop, it doesn't draw my box and it eats up 100% of my CPU when I move my "character".
#include <iostream>
#include <curses.h>
int main(){
std::pair<int,int> csr_pos{1,1};
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
nodelay(stdscr, TRUE);
curs_set(0);
WINDOW *win = newwin(50,80,0,0);
if(has_colors()){
start_color();
init_pair(1,COLOR_CYAN,COLOR_BLACK);
init_pair(2,COLOR_RED,COLOR_BLACK);
init_pair(3,COLOR_WHITE,COLOR_RED);
init_pair(4,COLOR_YELLOW,COLOR_BLACK);
}
/*
wattron(win,COLOR_PAIR(1));
mvwaddch(win,25,41,'@');
wattroff(win,COLOR_PAIR(1));
*/
for(int i = 0; i<80; i++){
mvwaddch(win,0,i,'#');
mvwaddch(win,49,i,'#');
wrefresh(win);
}
for(int i = 1; i<49; i++){
mvwaddch(win,i,0,'#');
mvwaddch(win,i,79,'#');
wrefresh(win);
}
while(true){
mvwaddch(win,csr_pos.first,csr_pos.second,'@');
int ch = getch();
if(ch==KEY_LEFT){
mvwaddch(win,csr_pos.first,csr_pos.second,' ');
csr_pos.second--;
mvwaddch(win,csr_pos.first,csr_pos.second,'@');
}
if(ch==KEY_RIGHT){
mvwaddch(win,csr_pos.first,csr_pos.second,' ');
csr_pos.second++;
mvwaddch(win,csr_pos.first,csr_pos.second,'@');
}
wrefresh(win);
}
}
nodelay(stdscr, TRUE);
Let's take a look at what the curses manual page says about this:
nodelay
The nodelay option causes getch to be a non-blocking call. If no input
is ready, getch returns ERR. If disabled (bf is FALSE), getch waits
until a key is pressed.
If that wasn't clear: in nodelay mode getch
does not wait for a keypress. It returns immediately.
Let's see what the shown code does next:
while(true){
mvwaddch(win,csr_pos.first,csr_pos.second,'@');
int ch = getch();
// ...
So, this now becomes a 100% CPU bound infinite loop. getch
always returns immediately. If neither of the two keys that the following code checks for are pressed, this while
loop immediately runs again, and you're back where you started, over and over again.
And that's the reason why the shown code "eats up 100%" of the CPU.
nodelay
mode is meant to be used with additional logic that poll()
s or select()
s until there's a keypress, and getch
gets called only when there's an actual key to be read.