我尝试使用ascii角色制作游戏,但闪烁过多

问题描述

我做了一个游戏。它基本上是这样的。每半秒钟输入一次if条件,然后进行一切计算,然后将所有内容打印到控制台。这是我的游戏循环。

//game loop
    while(!IsGameOver)
    {
        // Updates every half a second
        if ((int)(ElapsedTime / 500) > PreviousRoundQSec)
        {
            PreviousRoundQSec = (int)(ElapsedTime / 500);

            BulletCalculation(bullets);
            RemoveBulletsOutsideOfTheBoard(bullets,BoardLength);
            HealthCalculation(SpaceShips,bullets);
            RemoveDead(SpaceShips,bullets);
            DrawGame(BoardWidth,BoardLength,SpaceShips,bullets);
        }
        
        // Updates EverySecond
        if ((int)(ElapsedTime / 1000) > PreviousRoundSec)
        {
            PreviousRoundSec = (int)(ElapsedTime / 1000);


            PreDir = HordLogic(SpaceShips,bullets,BoardWidth,PreDir,PreNearBorder);
            
        }

        IsGameOver = GameOver(SpaceShips);

        // To keep time
        auto end = chrono::steady_clock::now();
        ElapsedTime = chrono::duration_cast<chrono::milliseconds>(end - start).count();
    }

起初,我尝试cout计算完每个字符。但是它的打印效果很差,您可以看到单独打印每个字符。那确实很糟糕。在互联网上进行搜索后,我发现printf func更快,但也没有真正帮助到我。我最后的灵魂是在字符串中添加evey字符并立即打印该字符串。这是最好的解决方案,但还不够,因为您可以看到游戏闪烁,这会使一切变得复杂。

这是我的绘图功能的最新版本。

void DrawGame(int BoardWidth,int BoardLength,vector<Entity*> &SpaceShips,vector<Bullet> &bullets)
{
    system("cls");

    string screen = "";
    for (int x = 0; x < BoardWidth + 2; x++)
    {
        screen += (char)178;
    }
    screen += "\n";
    for (int y = 1; y < BoardLength + 1; y++)
    {
        for (int x = 0; x < BoardWidth + 2; x++)
        {
            if (x == 0 || x == BoardWidth + 1)
            {
                screen += (char)178;
            }
            else
            {
                bool enteredIf = false;
                for (int i = 0; i < SpaceShips.size(); i++)
                {

                    // Tough Enemy drawing
                    if (SpaceShips[i]->x == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 't')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 't')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 't')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 't')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 't')
                    {
                        screen += "#";
                        enteredIf = true;
                    }

                    //Idle Enemy drawing
                    if (SpaceShips[i]->x == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 'i')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 'i')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 'i')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 'i')
                    {
                        screen += "U";
                        enteredIf = true;
                    }
                    
                    //Shooting Enemy Drawing
                    if (SpaceShips[i]->x == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 's')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 's')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 's')
                    {
                        screen += "#";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 's')
                    {
                        screen += "/";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 's')
                    {
                        screen += "\\";
                        enteredIf = true;
                    }

                    //Player Drawing
                    if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y == y && SpaceShips[i]->type == 'p')
                    {
                        screen += "^";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 'p')
                    {
                        screen += "<";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 1 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 'p')
                    {
                        screen += "_";
                        enteredIf = true;
                    }
                    else if (SpaceShips[i]->x + 2 == x && SpaceShips[i]->y + 1 == y && SpaceShips[i]->type == 'p')
                    {
                        screen += ">";
                        enteredIf = true;
                    }
                }
                if (!enteredIf)
                {
                    screen += " ";
                }
            }
        }
        screen += "\n";
    }
    for (int x = 0; x < BoardWidth + 2; x++)
    {
        screen += (char)178;
    }

    // draw bullets
    for (int i = 0; i < bullets.size(); i++)
    {
        if (bullets[i].GetDir() == 's')
        {
            screen.at(((bullets[i].y * (BoardWidth + 3)) - 1) + (bullets[i].x + 1)) = (char)203;
        }
        else if (bullets[i].GetDir() == 'w')
        {
            screen.at(((bullets[i].y* (BoardWidth + 3)) - 1) + (bullets[i].x + 1)) = (char)202;
        }
    }

    screen += "\n Remaining lives: ";
    screen += itoa(SpaceShips[0]->hp);

    cout << screen;
}

这是游戏的外观(我没有看到任何禁止共享链接的规则。如果可以的话,欢迎提出警告):https://www.loom.com/share/1bcc97fa0cbe4ee3aec62e317b10fcd0

解决方法

您正在使用std::cout可能是问题所在。标准输出流与终端交互的方式是连续的行序列,随着新行的添加,它们自然会向上滚动。您需要与终端进行较低级别的交互,从而可以更好地控制其行为。

一个这样的选项是在Unix系统上使用ncurses library(在Windows命令行上使用PDCurses

这将允许您使用“固定”终端窗口,并在该固定窗口上设置字符的值。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...