I am trying to make a snake game in 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
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.
With this said, you need to create a method that both the thread and input loop exit. Currently both are infinite loops.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.