Reputation: 141
So I recently found curses (specifically PDcurses) and I'm just getting into it. Right now I'm trying to write a little space shooter type game with it and it's worked fine so far for rendering and getting menu type input, but now when I go into the game, I've noticed that key repeat is pretty bad for action games. I need to be able to hold the key and move my avatar every single frame that the key is down. I know how to do this with a normal Win32 application, but I don't have a window and therefore I don't have a wndproc and I can't control the messages the console recieves :/
I don't expect this is something for curses to handle, though if it can that would be awesome, I was really just looking for a work-around that plays nicely with curses.
I have tried cbreak(), nodelay() and raw() to no avail.
Additional info:
Upvotes: 2
Views: 2168
Reputation: 9039
This is far from a complete solution, and I don't know how it'll interact with PDCurses, but it's an attempt:
In summary, grab the console's handle with GetStdHandle()
, configure it for raw reading with SetConsoleMode()
, and then read keys one at a time with ReadConsoleInput()
. I use a std::set
to keep track of the currently pressed keys and so ignore repeats.
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <cassert>
#include <set>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
BOOL success;
success=GetConsoleMode(h, &mode);
assert(success);
mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
mode |= ENABLE_WINDOW_INPUT;
success=SetConsoleMode(h, mode);
assert(success);
INPUT_RECORD buffer[10];
std::set<WORD> keys_down;
while (true)
{
DWORD count=0;
success=ReadConsoleInput(h, buffer, 10, &count);
if (!success)
{
continue;
}
for (size_t i=0;i<count;++i)
{
switch (buffer[i].EventType)
{
case KEY_EVENT:
{
WORD keycode=buffer[i].Event.KeyEvent.wVirtualKeyCode;
if (buffer[i].Event.KeyEvent.bKeyDown)
{
if (keys_down.find(keycode)==keys_down.end())
{
std::cout<<"Key down: "<<keycode<<std::endl;
keys_down.insert(keycode);
}
}
else
{
if (keys_down.find(keycode)!=keys_down.end())
{
std::cout<<"Key up:"<<keycode<<std::endl;
keys_down.erase(keycode);
}
}
break;
}
default:
break;
}
}
}
}
Upvotes: 2