2

I'm writing a simple console game and I'm having problems with console flickering (i think system("cls") might be the issue?). I tried using double buffers but I messed it up I guess.I know Move() function doesnt work fully correct but it's enough to show movement on console. I'm also unsure about kbhit and getch, since usage of these is not recommended. What are some good alternatives?

    void Snake::DrawBuffer()
{
    for (int i = 0; i < HEIGHT; i++)
    {
        for (int j = 0; j < WIDTH; j++)
        {
            std::cout << buffer[WIDTH * i + j];
        }
        std::cout << '\n';
    }
}

void Snake::WriteNextBuffer()
{
    for (int i = 0; i < WIDTH * HEIGHT; i++)
        nextbuffer[i] = ' ';

    for (int i = 0; i < length; i++)
        nextbuffer[body[i]] = 'o';

}

void Snake::WriteBuffer()
{
    for (int i = 0; i < WIDTH * HEIGHT; i++)
    {
        buffer[i] = nextbuffer[i];
    }
}

void Snake::Move()
{
    char key;

    if (_kbhit())
        key = _getch();
    else
        key = lastkey;
    switch (key)
    {
    case 'w':
        if (lastkey != 's')
        {
            body.pop_back();
            body.emplace(body.begin(), head - WIDTH);
        }
        break;
    case 's':
        if (lastkey != !'w')
        {
            body.pop_back();
            body.emplace(body.begin(), head + WIDTH);
        }
        break;
    case 'a':
        if (lastkey != 'd')
        {
            body.pop_back();
            body.emplace(body.begin(), head - 1);
        }
        break;
    case 'd':
        if (lastkey != 'a')
        {
            body.pop_back();
            body.emplace(body.begin(), head + 1);
        }
        break;
    }
    head = body[0];
    lastkey = key;
}

void Snake::Frame()
{
    Move();
    WriteNextBuffer();
    WriteBuffer();
    DrawBuffer();
}

void Snake::Game()
{
    while (1)
    {
        Frame();
        system("cls");
    }
}
  • 1
    You might find working with [PDCurses](https://github.com/Bill-Gray/PDCurses) is nicer than trying to do it by hand. – Eljay Mar 21 '20 at 01:26
  • 1
    How much of the screen changes at once? Maybe you could draw the background only once and use [SetConsoleCursorPosition](https://learn.microsoft.com/en-us/windows/console/setconsolecursorposition) to only change the parts of the screen that really change. That will minimize the flickering. – Andreas Wenzel Mar 21 '20 at 01:29
  • 1
    Usage of platform-specific functions such as `_getch` and `_kbhit` is not recommended if you want your code to be portable to other platforms, such as Linux. However, I'm afraid you will have to sacrifice portability in this case and use functions that are specific to the Windows platform, because there is no other way to accomplish what you want. – Andreas Wenzel Mar 21 '20 at 01:33
  • 1
    You may be able to create a second console screen buffer using the [`CreateConsoleScreenBuffer`](https://learn.microsoft.com/en-us/windows/console/createconsolescreenbuffer) function. I found [this example code](https://gist.github.com/enghqii/c8711c5f04d3f3d2f8f2) which uses it. – Andreas Wenzel Mar 21 '20 at 01:49

0 Answers0