【问题标题】:C++ console game input && refresh functionC++控制台游戏输入&&刷新功能
【发布时间】:2010-10-28 09:03:50
【问题描述】:

我正在编写一款小型主机冒险游戏,但遇到了一些问题。
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;
}

【问题讨论】:

  • getch()第一次返回的值是多少?
  • 第一次没有返回任何东西(循环没有运行),我已经添加了上面的代码。

标签: c++ input game-engine


【解决方案1】:

不要使用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');

【讨论】:

  • 这些函数来自什么库?
  • 你必须包含 windows.h
【解决方案2】:
  1. 整个代码中应该只有一个 getch() (如果可能的话),并且在一个开关中,您可以为每个输入执行操作。所以,它是循环内的开关,而不是开关内的循环。像这样的:

    while ((ch = getch()) != 'q') { 开关 (ch) { 案例“一”: 往左走(); 休息; ... } }

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

【讨论】:

  • 1.我现在已经添加了代码。 2. 谢谢,如果没有其他选择,我会使用 ncurses,但我想坚持使用默认库。
  • 没有用于显示绘图的默认库,因为在某些硬件中可能根本没有显示。而且我认为这不是全部相关代码。您的代码中是否有多个 getch?
  • 是的,我有 5 个(W、A、S、D 用于控制,Q 用于退出)。我应该粘贴整个代码吗?大多数变量不是英文的,因此理解其中一些可能会很复杂。
  • 在您发布的代码中有一个“master getch”while 循环,用于检查输入键是否为“q”。这个 getch 正在“吃掉”你的第一把钥匙。根据我编辑的答案更改代码。不幸的是,代码格式化停止工作,但代码仍然有效。
【解决方案3】:

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

【讨论】:

  • 谢谢!您和 flagbug 的解决方案有效,如果可能的话,我会接受这两个答案。
  • 我不能 - 它需要 15 声望:/
【解决方案4】:

我建议您按原样使用函数 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();
   }
}

这样你在计算之前总是有某种输入值,然后你就可以绘制(+它更容易调试;))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多