I'm making an ASCII art game in c (windows), but for some reason when i play it is all flickering at apparently random intervals, and for most of the time i can't see anything. can anyone explain why or how to solve it?
this is my code:
const int WIDTH = 20, HEIGTH = 5;
const int AREA = (WIDTH) * HEIGTH;
const int gl = HEIGTH - 2; //Ground level
const float delta = 0.1f; //Frame rate
char scr[AREA]; //String for displaying stuff
char input;
int posx = 10, posy = gl - 1; //Player position
int vel = 0; //player velocity
while(1)
{
//TODO: player input
for(i = 0; i < AREA; i ) //Rendering part
{
if(i % WIDTH == 0 && i != 0)
{
scr[i] = '\n';
continue;
}
if(floor(i / WIDTH) >= gl) //i is on ground
{
scr[i] = '.';
continue;
}
scr[i] = ' ';
}
//Set player position
scr[posy * WIDTH posx 1] = '@';
scr[(posy 1) * WIDTH posx 1] = '@';
system("cls");// Clear terminal
printf(scr);// Print screen
usleep(delta * 1000);//Sleep
}
output:
@
..........@........
...................►↓@
It works, but it flickers...
CodePudding user response:
One possible reason for your problem is that there may be output waiting in the output buffer when you call your sleep function usleep
. In that case, you should always flush all output before sleeping, by calling the function fflush( stdout );
.
Also, using system("cls");
is highly inefficient. It is generally better to use the Console Functions API, or, if you are targetting platforms with Windows 10 or later, you can also use Console Virtual Terminal Sequences instead.
If you decide to use the Console Functions API, then the main functions that you will be needing in order to replace system("cls");
are GetStdHandle
to obtain the output handle, and SetConsoleCursorPosition
. That way, you won't have to clear the whole screen, but will only have to overwrite the parts of the screen that are changing. I also recommend that you replace printf
with WriteConsole
, otherwise you may run into buffering issues.
If this does not solve your flickering problem, then there also is the possibility of using double-buffering. Both the Console Functions API and Console Virtual Terminal Sequences support this.
When using the Console Functions API, you can use the function CreateConsoleScreenBuffer
to create a new buffer to write to, without it being displayed immediately. This will allow you to first finish building the next screen, without any flickering occuring while doing so (because it is not being displayed yet). Once you have finished building the next screen, you can display it using the function SetConsoleActiveScreenBuffer
.
Console Virtual Terminal Sequences offer similar functionality by supporting an alternate screen buffer.