简体   繁体   English

线程运行时C ++按下箭头键

[英]C++ get arrow key press while a thread is running

I am trying to make a snake game in c++. 我正在尝试用C ++制作蛇游戏。 I have a thread that moves the snake's head in the direction that the user specifies with the arrow keys. 我有一个线程,可按用户使用箭头键指定的方向移动蛇的头部。 if I press the up arrow key I need the head to move up and continue moving (this is done by the thread) without me pressing the arrow keys. 如果按向上箭头键,我需要头部向上移动并继续移动(这是通过线完成的),而无需按箭头键。

The issue is i can't get the keyboard input to work together with the thread, its either one function works or its the other, they can't work together 问题是我无法使键盘输入与线程一起工作,它的一个功能或另一个功能都不能工作,它们不能一起工作

Keyboard input function: 键盘输入功能:

void moveSnake()
{
    while(true)
    {
        int key = getch();
        switch(key)
        {
        case 72:
        {
              //UP
              break;
        }
        case 80:
        {
              // DOWN
              break;
        }
        case 77:
        {
             // RIGHT
              break;
        }
        case 75:
        {
             // LEFT
              break;
        }
    }
}

Thread function: 线程功能:

void thread_handler()
{
    while(true)
    {
        // Move the snake
        Sleep(500);
    }
}

This is where i create the thread and call the keyboard function 这是我创建线程并调用键盘功能的地方

int main()
{
    moveSnake();
    thread t(thread_handler);
    t.join();
    return 0;
}

I have tried 我努力了

  • putting moveSnake() in a thread 将moveSnake()放入线程
  • executing the thread_handler function without a thread 在没有线程的情况下执行thread_handler函数
  • tried to put both functions in a separate thread 试图将两个功能放在单独的线程中
  • tried switching the order with all these possible solutions 尝试使用所有这些可能的解决方案切换订单

But none of these worked. 但是这些都不起作用。

I need a way to get the keycode for the arrow keys while running the thread at the same time 我需要一种在同时运行线程的同时获取箭头键的键码的方法

Follow your source code like the compiler would, from top to bottom. 像编译器一样,从头到尾遵循源代码。 Your debugger can help you step through it. 调试器可以帮助您逐步进行调试。 You've went into a never ending loop in your main thread. 您在主线程中陷入了永无止境的循环。 What comes after that doesn't matter because you never get there. 之后发生的事情并不重要,因为您永远都不会到达那里。

Even if you switch the ordering of things, you've still got a never ending loop, so you cannot join properly after you call it. 即使切换事物的顺序,您仍然会有一个永无止境的循环,因此调用它后就无法正确加入。

You need to read up on some basic threading lessons. 您需要阅读一些基本的线程课程。 Just because you are using threads doesn't mean you can stop worrying about whether loops exit or not. 仅仅因为您正在使用线程并不意味着您可以停止担心循环是否退出。 Loops should always have some exit condition. 循环应始终具有一些退出条件。

For your program, I'd assume you'd want to start a thread to handle the input, lock some manner of storage and read key presses. 对于您的程序,我假设您想启动一个线程来处理输入,锁定某种存储方式并读取按键。 Back in your main thread, you'd probably want to loop until some signal for exit, lock and get the stored key press/command (maybe use a thread safe queue?), and react to it. 回到您的主线程中,您可能想要循环直到出现退出信号,锁定并获取存储的按键/命令(也许使用线程安全队列?)并对之做出反应为止。

Here is a very simple and naive example: 这是一个非常简单且幼稚的示例:

#include <mutex>
#include <thread>
#include <queue>

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

class Application
{
public:

    void Run()
    {
        // Start input thread
        if (m_inputThread.joinable())
        {
            Shutdown();
        }

        auto thread = std::thread(std::bind(&Application::InputThreadProc, this));
        m_inputThread.swap(thread);

        while (!m_shutdown)
        {
            // React to the queued input, including checking for shutdown
            // I'm just going to ignore the complex issue of timing
            std::this_thread::sleep_for(std::chrono::milliseconds(33));
            std::lock_guard<std::mutex> lock(m_mutex);
            if( !m_keysPressed.empty() )
            {  
                auto key = m_keysPressed.front();
                m_keysPressed.pop();

                switch (key)
                {
                case 75:
                    m_shutdown = true;
                default:
                    std::cout << "I saw a key: " << key << std::endl;
                    break;
                }
            }
        }

        Shutdown();
    }

private:

    std::mutex      m_mutex;
    std::queue<int> m_keysPressed;
    bool            m_shutdown = false;
    std::thread     m_inputThread;

    void Shutdown()
    {
        if (m_inputThread.joinable())
        {
            m_inputThread.join();
        }
    }

    void InputThreadProc()
    {
        while (!m_shutdown)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(33));
            std::lock_guard<std::mutex> lock(m_mutex);

            // OS Specific. Better means of getting localized input exist.
            // Also, timing is an issue. Is the key pressed when we are trying to read.
            // Input is a complex topic and many libraries for it exist
            m_keysPressed.emplace(_getch());
        }
    }
};

int main()
{
    Application application;
    application.Run();

    return 0;
}

Change the order of your main to 将主订单的顺序更改为

int main()
{
    thread t(thread_handler);
    moveSnake();
    t.join();
    return 0;
}

this way the thread is started before your input loop (which is an endless loop). 这样,线程将在您的输入循环(这是一个无穷循环)之前启动。 Make sure you leave the t.join() at the end. 确保最后保留t.join()

With this said, you need to create a method that both the thread and input loop exit. 如此说来,您需要创建一个线程和输入循环都退出的方法。 Currently both are infinite loops. 当前两者都是无限循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM