How to juggle between windows (game and pause window) in ncurses?

70 views Asked by At

I am creating a game in C. I'm not playing it in stdscr, but in a win called basewin. I want, when the user press 'P', to open another window, called pausewin, and pause the game running on basewin. Then, when the user press 'R' for resume, I want to "close" pausewin, and get my game resumes. Especially, I want to see my basewin in the same state I left it before pressing 'P'.

I was thinking I can do that by using window because:

  1. It would make my code cleaner.
  2. Windows are pointer on memory space, so I can restore basewin easily.
  3. It will be a general method to pause any game, without getting trouble with printw after quitting pausewin.

But my idea didn't work. I tried this on a simplified game:

#include <ncurses.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <stdlib.h> 
    
int main() {
    /* INIT NCURSES */ 
    initscr(); 
    curs_set(0); 
    noecho();
    
    /* INIT PAUSE WIN */
    WINDOW *pausewin = newwin(LINES/3, COLS/3,LINES/3, COLS/3);
    keypad(pausewin,TRUE);
    int cMax_pause, lMax_pause; getmaxyx(pausewin,lMax_pause, cMax_pause);
    box(pausewin,0,0);
    mvwprintw(pausewin,1,cMax_pause/2 -5,"PAUSE WIN");
    mvwprintw(pausewin,lMax_pause/2, cMax_pause/3-4, "[R]ESUME");
    mvwprintw(pausewin,lMax_pause/2, 2*cMax_pause/3-3, "[Q]UIT");
    
    /* INIT BASE WIN */
    WINDOW *basewin = newwin(LINES, COLS/2, 0, COLS/4);
    keypad(basewin,TRUE);
    int lMax, cMax; getmaxyx(basewin, lMax, cMax);
    box(basewin,0,0);
    mvwprintw(basewin,0,2, "[P]AUSE");
    mvwprintw(basewin,1,cMax/2 -4,"BASE WIN");
    
    /* INIT VAR */
    bool loop = true;
    bool pause = false;
    int ch,chp;
    
    /* INIT VARS PLAYER */
    int pline = lMax/2;
    int pcol = cMax/2;
    char pch[2] ; pch[0] = 'M';
    
    /* AFFICHAGE BASE WIN : PRE-LOOP */
    wrefresh(basewin);
    
    /* "GAME" LOOP */
    while(loop){
        
        ch = wgetch(basewin);
        switch(ch){
            case 'p': /* On met le jeu en pause */
            case 'P':
                pause = true;
                break;
            case KEY_LEFT: /* Sinon deplacement */
                pcol -= 1;
                break;
            case KEY_RIGHT:
                pcol += 1;
                break;
            case KEY_UP:
                pline -= 1;
                break;
            case KEY_DOWN:
                pline += 1;
                break;
            default:
                break;
        }
    
    if (pause){
        wrefresh(pausewin);  // HERE IS THE PLACE I HAVE MY PROBLEM
        while(pause){
            chp = wgetch(pausewin);
            switch (chp){
            case 'q':
            case 'Q':
                pause = false;
                loop = false;
                break;
            case 'r':
            case 'R':
                pause = false;
                wrefresh(basewin); // HERE TOO
                break;
            default:
                break;
            }
        }
        
    }
    
    else{
        mvwprintw(basewin,pline,pcol,pch);
    }
    
    wrefresh(basewin);
    }
    
    
    delwin(pausewin);
    delwin(basewin);
    endwin();
    return EXIT_SUCCESS;
}

I have a relatively good comprehension of ncurses manual, but I can't get this working. I tried to solve that with a tempwin, but it work one time and then never print pausewin again. I also tried to use overwrite() but it doesn't really look like the good way to solve that.

1

There are 1 answers

0
Oka On

A very simple approach would be to call touchwin to indicate that the entire window should be redrawn to the screen.

(Note that wgetch(pausewin) implies wrefresh(pausewin) when the window has been modified [in this case marked as such by touchwin], otherwise wrefresh must be called to actually produce output. wrefresh(basewin) is called at the bottom of the main loop, regardless of the pause.)

if (pause) {
    touchwin(pausewin);

    while (pause) {
        chp = wgetch(pausewin);

        switch (chp) {
            case 'q':
            case 'Q':
                pause = false;
                loop = false;
                break;
            case 'r':
            case 'R':
                pause = false;
                touchwin(basewin);
                break;
            default:
                break;
        }
    }
}