Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

NumberXaero

Pro keyboard and mouse input

This topic is 5547 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Im trying to figure out how pro games handle input, things like the side step (dodge) in UT and the special abilities commands like the speed key combo in UT2K3. Do they use a timer along with the input to determine if it was done correctly in the right time frame, and if they do would they use the system time or a hi res timer. I started thinking about this cause Im using a combination windows/direct input and ive noticed both are too quick for things like console key input. Tapping a key the same way you would if you were entering a URL in a browser results in the key being repeated 6 times by the time you take your finger off. Im pluging in the input to the WM_CHAR and WM_KEYDOWN messages but they repeat too fast in one key stroke. Although i seen it done exactly the same way for a demo in a book i read and his didnt repeat that fast when i ran it. If anyone knows how i could control this repeat rate or if pro games use a timer of some sort to handle fast key sequences Id like to hear it. thanks.

Share this post


Link to post
Share on other sites
Advertisement
I recently made a system for console-like input and I think the topic is quite interesting, especially when you want the system to handle input just as well under low FPS. Mine is a bit messy at this point, but it does what it's supposed to and it does it well.

For the system to be bulletproof, you have to make sure it works well even when you have a very low update rate as mentioned. Assume that you put a sleep(10000) in your code and while the program is "sleeping" you type something on your keyboard and when the program gets past the sleep you'd want it to tell you what you typed. If your program can do this, you've succeeded. Of course such a senario wouldn't occur in a real game, but if you can handle the worst case, you can handle them all.

So to do this, you have to make the program aware of the timestamps of up- and down-events. The key, In my case, is to use DirectInput's buffered input (IDirectInput8Device::GetDeviceData). I dont use regular windows input at all.

When a key go down I use a structure of mine to store the scancode and time of keypress along with a repeatstate (which controls the delay. When a key is pressed, the first character appears immediatly, the second has a long delay and the rest has yet another delay) and a time of keyrelease (0, because it's unknown at this point). Then I push this structure on to a std::vector. If a key went up instead of down, I search the vector for the appropriate scancode (because all down-events are stored in the vector, it must be in there) and set the release time of this element.

When all the pressed/released keys have been processed I loop through the vector and compare all the elements time of keypress (repeatTimer) against time of release and the current time, depending on the repeatstate. Here I make use of the GetTickCount() to get the current time since it returns the time that have elapsed since the system was restarted, just like DirectInput's timestamps. If the comparation(s) evaluate to true, the repeatTimer is increased to start a new delay and the repeatState is updated. A bit simplified the repeat-loop looks like this:


DWORD tickCount = GetTickCount();
for ( int i=0 ; i<keyData.size() ; i++ )
{
if (keyData[i].repeatState==RS_INIT)
{
//The key was pressed, do whatever you'd like to here


keyData[i].repeatTimer += REPEATINITDELAY;
keyData[i].repeatState = RS_DELAY;
}
if (keyData[i].repeatState==RS_DELAY &&
tickCount>keyData[i].repeatTimer &&
(keyData[i].releaseTime==0 || keyData[i].releaseTime>keyData[i].repeatTimer))
{
//The character has been repeated, do whatever you'd like to here


keyData[i].repeatTimer += REPEATDELAY;
keyData[i].repeatState = RS_REPEAT;
}
while (keyData[i].repeatState==RS_REPEAT &&
tickCount>keyData[i].repeatTimer &&
(keyData[i].releaseTime==0 || keyData[i].releaseTime>keyData[i].repeatTimer))
{
//The character has been repeated, do whatever you'd like to here


keyData[i].repeatTimer += REPEATDELAY;
}
}


Afterwards, all the keys affected by an up-event are removed from the vector. Note that this cant be done before the loop I pasted above. If it is, the effect would be that keys pressed and released in the same frame (which can be the case when the FPS is low or when you're using a sleep(10000) ) will go unnoticed.

I realize that an explanation this vague wont be of much help directly although I hope this made it at least a bit clearer. If you want me to explain it in more detail with some real exemples or if you wish to take a look at the actual code or an example program, drop me an email and I'd be glad to help.

[edited by - Exellion on August 16, 2003 8:06:24 AM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!