Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ncurses clear() causes flickering

Tags:

c++

ncurses

I'm using ncurses for a typing game I'm making. Letters fall down the screen and you must type them before they reach the bottom. It's working great, save one problem. Clearing the window (with clear()) makes the output flicker. I put clear() at the very beginning of the loop and wrefresh() at the very end. Shouldn't it be waiting 'til wrefresh to show anything, thus not flashing?

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <curses.h>
#include <fstream>

using namespace std;

int main(){

  initscr();
  cbreak();
  noecho();
  keypad(stdscr, TRUE);
  nodelay(stdscr, TRUE);

  srand(time(NULL));

  //input character integer (ASCII)
  int ch = 1;
  //int to store the last time the character positions were updated
  int lastupdate = time(NULL);

  //x,y,char arrays for falling characters and initialization
  int chars[10], x[10], y[10];
  for(int i = 0; i < 10; i++){
    chars[i] = rand()%25 + 97;
    x[i] = rand()%30;
    y[i] = 0;
    //y[i] = -(rand()%4);
  }

  while (true){
    clear();
    ch = wgetch(stdscr);

    for (int i = 0; i < 10; i++){
      mvwdelch(stdscr,y[i]-1,x[i]);//delete char's prev. position
      mvwaddch(stdscr, y[i], x[i], chars[i]);//add char's current position
      if (ch == chars[i]){
        mvwdelch(stdscr, y[i], x[i]);
        chars[i] = rand()%25 + 97;
        x[i] = rand()%30;
        y[i] = 0;
      }
    }

    if(time(0) >= (lastupdate + 1)){
      for (int i = 0; i < 10; i++){
        y[i]++;
      }
      lastupdate = time(NULL);
    }

    wmove(stdscr, 20, 0);
    printw("your score is NULL. press ESC to exit");

    scrollok(stdscr, TRUE);
    wrefresh(stdscr);
  }
  endwin();
  return 0;
}

edit: added code

edit2: removed some irrelevant debug code

like image 870
Jeremy Avatar asked Feb 02 '18 00:02

Jeremy


2 Answers

I suggest to Just use erase() instead of clear() clear also calls clearok() automatically.

like image 168
Geek Wisdom Avatar answered Sep 20 '22 00:09

Geek Wisdom


The clear manual page is the place to start:

The clear and wclear routines are like erase and werase, but they also call clearok, so that the screen is cleared completely on the next call to wrefresh for that window and repainted from scratch.

The wgetch call does that wrefresh, which causes the repainting:

If the window is not a pad, and it has been moved or modified since the last call to wrefresh, wrefresh will be called before another character is read.

The description of wrefresh is not nearly so succinct, but "repainting from scratch" will cause flickering since there is a moment when the screen is empty, followed by it being non-empty. Those alternate rapidly due to this call:

nodelay(stdscr, TRUE);
like image 37
Thomas Dickey Avatar answered Sep 19 '22 00:09

Thomas Dickey