C ++ консольная игра и функция обновления - PullRequest
2 голосов
/ 28 октября 2010

Я пишу небольшую консольную приключенческую игру и столкнулся с несколькими проблемами.
1. Ввод немного запаздывает, я использую цикл while (while (getch () == 'w')). После первого нажатия клавиши ничего не происходит (вы должны нажать ее 2 раза), и если вы меняете направление (нажмите кнопку 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;
}

Ответы [ 4 ]

3 голосов
/ 28 октября 2010

Не используйте 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');
2 голосов
/ 28 октября 2010
  1. Код должен иметь только один getch () во всем коде (если возможно), и внутри переключателя вы выполняете действие для каждого входа.Таким образом, это переключатель внутри петли, а не петли внутри коммутатора.Примерно так:

    while ((ch = getch ())! = 'Q') {switch (ch) {case 'a': GoLeft ();перерыв;...}}

  2. Существует библиотека под названием ncurses , которую можно использовать для перемещения курсора по экрану и записи чего угодно в любом месте.

1 голос
/ 28 октября 2010

Похоже, ваша проблема вызывает функцию getch () несколько раз.Иметь только один цикл, вызывать getch () один раз за цикл и сохранять результат.Проверьте этот результат для каждого значения (q, w, s, ...) для каждой итерации цикла.

0 голосов
/ 30 ноября 2018

Я бы порекомендовал вам использовать функцию 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 (), которая останавливает вашу игру каждый раз.


Youможете использовать его с функциями draw () и calc () / refresh () в main (), например:

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

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

, чтобы перед вычислениями всегда было какое-то входное значение, итогда вы будете рисовать (+ это гораздо легче отлаживать;))

...