I'm trying to write a simple game working with two threads, one thread to get input from the user, and another thread to animate some scenes. I'm able to get characters without pressing ENTER just fine, but it blocks in the animating thread until the user presses a key. Does anyone know of a way to get a character from the keyboard non-blocking?
I have used rubygame for this. It gives you the ability to attach functions to keyboard events with minimal code. RubySDL and GoSu will give you similar functionality.
If you don't want to go that route with game related gems take a look at this on how to check if data is available in IO object. This could be use to poll the keyboard.
If you're looking to checkup on a handful of specific keys, GetAsyncKeyState()
can be used to poll for state. Otherwise, you should implement a message loop and handle WM_CHAR
messages in your application.
You can access raw win32 functions with a library similar to the following if your environment doesn't already support the win32 functions you need.
RAA - win32-api @ raa.ruby-lang.org
Here are relevant links for GetAsyncKeyState()
.
GetAsyncKeyState() @ MSDN
Virtual-Key Codes @ MSDN (used as values for GetAsyncKeyState and other functions)
If you decide to go with a message loop, you'll need to implement it on the same thread that hosts the window for your application. A short explanation is available here:
Message Loop in Microsoft Windows @ Wikipedia
As shown at that link, there isn't a whole lot to a message loop. Your framework may already have one running behind the scenes to host the window containing your graphics. If this is the case, you don't need a 2nd thread for input; but you will need to intercept and handle windows messages for that host window.
If you have to implement a message loop on your own, you can use the skeleton at the wikipedia link. The DispatchMessage
call will direct a windows message to the appropriate window handler. You will need to look for a matching stub or handler for windows messages in your ruby framework, and handle WM_CHAR
from there.
DispatchMessage @ MSDN
WM_CHAR @ MSDN
If you wish to know when keys are pressed/depressed, then you will want to handle WM_KEYUP and WM_KEYDOWN messages.
WM_KEYUP @ MSDN
WM_KEYDOWN @ MSDN
Also note, GetAsyncKeyState()
can be called and returns key state even while another application is in the foreground. Handle WM_ACTIVATE
and WM_SETFOCUS
/WM_KILLFOCUS
messages so that your application ignores or defers checks while a different window is active if you only care about key state while your window is the primary foreground window.