C++控制台游戏输入&&刷新功能

发布于 2024-09-29 16:34:45 字数 1982 浏览 1 评论 0原文

我正在编写一个小型控制台冒险游戏,但遇到了一些问题。
1.输入有点滞后,我使用 while 循环( while(getch() == 'w') )。第一次按下某个键后,没有任何反应(您必须按两次),如果您切换方向(按 A/D/S 键),它第一次也不会做出反应。如果你按住钥匙,它就可以正常工作。如何解决这个问题?
2。这是我用来刷新游戏的功能(按下按键时渲染游戏场景):

    void refresh(char map[Y][X])
{
    system("cls");
    for (int i = 0; i<UP; i++)
    {
        cout<<endl;
    }
    for (int i = 0; i<Y; i++)
    {
        for (int k = 0; k<LEFT; k++)
        {
            cout<<" ";
        }
        for (int j = 0; j<X; j++)
        {
            cout<<map[i][j];
        }
        cout<<endl;
    }
}

当我使用此功能一次时,没问题,但是当多次按下或按住按键时 - 游戏字段开始闪烁。我认为我只需要重绘字段的一部分(进行更改/移动),而不是整个字段。您能提供一些如何做到这一点的想法吗?

输入示例代码:

while(getch() == 'w')
    {
        if (map[y-1][x]!= WALL)
        {
        map[y-1][x] = CHARACTER;
        map [y][x] = ' ';
        y--;
        refresh(map);
        Sleep(SPEED); // this is unnecessary, SPEED is 0, I just kept it for tests
        }
    }

基本上,主要功能如下所示:

int main()
{
    (...) Variables (...)
    generateMap(FROM FILE);
    refresh(); // First initialization of the field
    while (getch() != 'q') // While not quitting
    {
    while(getch() == 'w')
    {
        if (THE FIELD ABOVE IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    while(getch() == 's')
    {
        if (THE FIELD BELOW IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    while(getch() == 'a')
    {
        if (THE FIELD ON THE LEFT IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    while(getch() == 'd')
    {
        if (THE FIELD ON THE RIGHT IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    return 0;
}

I am writing a small console adventure game and I faced a few problems.
1. The input is kinda laggy, I'm using while loop ( while(getch() == 'w') ). After a key is pressed the first time, nothing happens (you have to press it 2 times) and if you switch directions (press key A/D/S) it also doesn't react the 1st time. If you hold a key, it works fine. How can this be fixed?

2. Here's the function I use to refresh game (render the game scene when a key is pressed):

    void refresh(char map[Y][X])
{
    system("cls");
    for (int i = 0; i<UP; i++)
    {
        cout<<endl;
    }
    for (int i = 0; i<Y; i++)
    {
        for (int k = 0; k<LEFT; k++)
        {
            cout<<" ";
        }
        for (int j = 0; j<X; j++)
        {
            cout<<map[i][j];
        }
        cout<<endl;
    }
}

When I use this function once, it's ok, but when they key is pressed or held multiple times - the game field starts to flash. I figured that I need to redraw only a part of the field (where changes are made/movements are done), not the whole field. Can you offer any ideas how to do that?

The sample code for input:

while(getch() == 'w')
    {
        if (map[y-1][x]!= WALL)
        {
        map[y-1][x] = CHARACTER;
        map [y][x] = ' ';
        y--;
        refresh(map);
        Sleep(SPEED); // this is unnecessary, SPEED is 0, I just kept it for tests
        }
    }

Basically, the main function looks like this:

int main()
{
    (...) Variables (...)
    generateMap(FROM FILE);
    refresh(); // First initialization of the field
    while (getch() != 'q') // While not quitting
    {
    while(getch() == 'w')
    {
        if (THE FIELD ABOVE IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    while(getch() == 's')
    {
        if (THE FIELD BELOW IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    while(getch() == 'a')
    {
        if (THE FIELD ON THE LEFT IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    while(getch() == 'd')
    {
        if (THE FIELD ON THE RIGHT IS NOT OCCUPIED)
        {
             setSomeVariables();
             refresh(THE GAMEFIELD);
        }
    }
    }
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蓝梦月影 2024-10-06 16:34:45

不要使用 system("cls"),它真的很慢,而是使用以下代码将光标设置在屏幕的开头:

COORD cur = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cur);

您应该调用 getch() 循环中只有一次,如下所示:

char key;

do
{
    key = getch();

    if(key == 'w')
    {
        //do something
    }

    //the other if statements

}while(key != 'q');

Don't use system("cls"), it is really slow, instead set the cursor on the beginning of the screen with the following code:

COORD cur = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cur);

You should call getch() only one time in the loop, like this:

char key;

do
{
    key = getch();

    if(key == 'w')
    {
        //do something
    }

    //the other if statements

}while(key != 'q');
2024-10-06 16:34:45
  1. 整个代码中应该只有一个 getch() (如果可能的话),并且在开关内对每个输入执行操作。所以,它是循环内的开关,而不是开关内的循环。像这样的事情:

    while ((ch = getch()) != 'q')
    {
    开关(通道)
    {
    情况“a”:
    左转();
    休息;
    ...
    }
    整个代码中的代码应该只有一个 getch() (如果可能),并且

  2. 有一个名为 ncurses 的库,您可以使用它在屏幕上移动光标,并在任何地方编写任何内容。

  1. The code should have only one getch() in the whole code (if possible) and inside a switch you do the action for each input. So, it is switch inside the loop, and not loops inside the switch. Something like this:

    while ((ch = getch()) != 'q')
    {
    switch (ch)
    {
    case 'a':
    GoLeft();
    break;
    ...
    }
    }

  2. There is a library called ncurses that you can use to move the cursor around the screen, and write anything anywhere.

与君绝 2024-10-06 16:34:45

看来您的问题是多次调用 getch() 。只有一个循环,每个循环调用一次 getch() ,并存储结果。测试循环每次迭代的每个值(q、w、s、...)的结果。

It looks like your problem is calling getch() multiple times. Have only one loop, and call getch() once per loop, and store the result. Test that result for each value (q, w, s, ...) for each iteration of the loop.

白芷 2024-10-06 16:34:45

我建议您按原样使用 function input() :

void input()
{   if (GetKeyState('W') & 0x8000)    // That means when button "W" is pressed
       ... your code ... 
     // (changes global variables, or you can pass variables by reference)
}

没有任何每次都会停止游戏的 getch() 命令。


您可以将它与 main() 中的draw() 和calculate()/refresh() 函数一起使用,例如:

int main()
{
   ... other part of code ...

   while (!gameover)
   {
      input();
      calculate();
      draw();
   }
}

这样您在计算之前总是有某种输入值,然后您将绘制(+它很多)更容易调试;))

I would recommend you to use function input() as it stands:

void input()
{   if (GetKeyState('W') & 0x8000)    // That means when button "W" is pressed
       ... your code ... 
     // (changes global variables, or you can pass variables by reference)
}

without any getch() command that stops your game every single time.


You can use it with the draw() and calculate()/refresh() functions in the main(), like:

int main()
{
   ... other part of code ...

   while (!gameover)
   {
      input();
      calculate();
      draw();
   }
}

so that you will always have some sort of input value before the calculations, and then you would draw (+ it's much easier to debug ;) )

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文