动画 ASCII 艺术在 c 中闪烁

Animated ASCII art flickering in c

我正在用 c (windows) 制作一个 ASCII 艺术游戏,但由于某种原因,当我玩它时,它会以明显随机的间隔闪烁,而且大部分时间我都看不到任何事物。谁能解释为什么或如何解决它?

这是我的代码:

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
}

输出:

          @
..........@........
...................►↓@

能用,就是闪烁...

您的问题的一个可能原因是当您调用休眠函数时,输出缓冲区中可能有输出等待 usleep。在这种情况下,您应该始终在休眠前刷新所有输出,方法是调用函数 fflush( stdout );.

此外,使用 system("cls"); 效率非常低。通常最好改用 Console Functions API, or, if you are targetting platforms with Windows 10 or later, you can also use Console Virtual Terminal Sequences

如果您决定使用控制台功能 API,那么您将需要替换 system("cls"); 的主要功能是 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,否则您可能 运行进入缓冲问题。

如果这不能解决你的闪烁问题,那么也有可能使用double-buffering. Both the Console Functions API and Console Virtual Terminal Sequences支持这个。

使用控制台函数API时,可以使用函数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

控制台虚拟终端序列通过支持 alternate screen buffer.

提供类似的功能