_getch как будто останавливает мою программу

Название довольно наглядно. По сути, я делаю Space Invaders в окне консоли в C++, это называется ASCII invaders. Кажется, в игре все работает нормально, за исключением одной серьезной проблемы: _getch приостанавливает работу программы. Я вызываю _kbhit, чтобы проверить, вводит ли игрок данные игрока, и если да, то использую _getch, чтобы получить ключ и действовать правильно. Игрок перемещается влево / вправо очень хорошо, но когда игрок нажимает "Пробел" или стреляет, программа приостанавливается до тех пор, пока вы снова не нажмете "Пробел", в этот момент он также будет стрелять.

Очевидно, что игрок не хочет этого в игре. Так что хотелось бы знать, как это исправить. Вот где это называется:

/***************************************/
/*          move_player();             */
/*      Calculates player movement     */
/*Returns weather or not toQuitTheGame */
/***************************************/
bool move_player()
{
    bool ret = false;
    //If a key is pressed
    if (_kbhit())
    {
        //Get key
        _getch();
        int key = _getch();
        //Check is the player moves left
        if (key == LEFT && object_handle.player_obj.x > 0)
        {
            //Move left
            object_handle.player_obj.x -= 1;
        }

        //Check is the player moves right
        if (key == RIGHT && object_handle.player_obj.x < 79)
        {
            //Move right
            object_handle.player_obj.x += 1;
        }

        //Check is the player is shooting
        if (key == SHOOT)
        {
            //shoot by creating the bullet above the player
            object_handle.bullet_obj.x = object_handle.player_obj.x;
            object_handle.bullet_obj.y = object_handle.player_obj.y - 1;
            object_handle.bullet_obj.active = true;
        }

        //Weather or not to kill the program
        if (key == VK_ESCAPE)
        {
            ret = true;
        }
        else
        {
            ret = false;
        }
    }
    return ret;
}

В качестве примечания, если вы просто прокручиваете мысль "Это много кода... Я не хочу иметь дело с этим". (Я делаю это иногда - не придираюсь к вам), обратите внимание, это не так уж и много, я просто использую комментарии и много пустого пространства.

И если вы хотите знать, вот вся "основная" функция.

int main()
{
    bool quit = false;
    object_handle.set_info();

    //Display main manu
    menu();

    //Main game loop
    while(!quit)
    {
        //Update past object variables
        object_handle.xy_update();

        //Calculate player movements
        quit = move_player();

        //Calculate bullet movements
        handle_objects();

        //Finally, update the screen
        screen_update();

        //DEBUG CODE
        debug();

        //Display score/stats
        stats();

        //Wait a given time before continuing the loop
        Sleep(INTERVAL);
    }
    cout << "\n\n\n\n\nBye" << endl;
    Sleep(1000);
    return 0;
}

Я включил все необходимые библиотеки, я не получаю ошибок компиляции.

Ах, да, прежде чем я забуду. Вот константы:

/******************CONSTANTS********************/
const int ENEMY_COUNT   = 15;
const int INTERVAL      = 250;
const int LEFT          = 75;
const int RIGHT         = 77;
const int SHOOT         = VK_SPACE;
const int BULLET_SPEED  = 8;
/***********************************************/

Любая помощь очень ценится!

3 ответа

Как объяснено в документации When reading a function key or an arrow key, each function must be called twice; the first call returns 0 or 0xE0, and the second call returns the actual key code.

Итак, вам нужно проверить, что возвращается, чтобы узнать, следует ли вам снова вызывать функцию.

Вот пример того, что вы должны быть в состоянии адаптироваться к вашим потребностям:

#include <conio.h>
#include <iostream>

int main()
{
    std::cout << "Type stuff, press x to quit.\n";
    int count = 0;
    for(;;)
    {
        //To show the loop isn't blocked
        if((++count % 1000) == 0)
        {
            std::cout << ".";
        }
        if(_kbhit())
        {
            int key = _getch();
            if(key == 0 || key == 0xE0)
            {
                key = _getch();
            }
            std::cout << "\nKeycode: " << key << "\n";
            if(key == 'x')
            {
                break;
            }
        }
    }
    return 0;
}

Вы также можете рассмотреть ReadConsoleInput Семейство функций, так как это дает вам больше гибкости. Вот пример из MSDN.

Попробуйте изменить:

_getch();
int key = _getch();

чтобы:

int key = _getch();

в вашем move_player функция.

Когда вы звоните _getch() дважды, в первый раз, он не записывает ключ, просто висит там, пока вы не нажмете клавишу снова, потому что тогда _getch() присваивается переменной key, Следовательно, вы должны удалить шальные _getch() в вашем move_player() функция.

Как уже упоминалось @RetiredNinja, вам нужно позвонить _getch() дважды, так что вам нужно установить проверку на первом _getch() установить, нажали ли вы клавишу алфавита или специальную клавишу.

Другие вопросы по тегам