Archived

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

smokes

DirectInput is too fast

Recommended Posts

I''m currently coding a nice little console. I''m polling a DirectInput keyboard device for input. My problem is that the console receives the character several times because I am only checking if the key is pressed.. and when it is pressed for multiple frames (hard to avoid unless you could tap it 60 times a second :-) I get the same character sprayed all over the screen.. Could I solve this problem by just polling the input say to or three times a second.. or should I somehow implement a KeyReleased() function.. I guess the last option is the only way to go.. I would like to get some ideas of how to build the state machine required for this from some of you who already done it.. and I don''t want to "just use the windows messages" else I would not have written a DirectInput wrapper :-)

Share this post


Link to post
Share on other sites
In my wrapper for DI, I have access for both "pressed" and "down", since they have different uses. The pressed is handy for typing in text or anything where you only want it to happen once per "press", but the down is often crucial for controls (moving, maybe firing, etc...).

There are a number of sample DI wrappers out there that are fine starting places if you''re wondering how best to implement it.

Onnel

Share this post


Link to post
Share on other sites
Onnel:
what is the difference between pressed and down?!?

sleekgeekfreak:
You couldn''t explain to me what a debouncer is? and how it works?

Share this post


Link to post
Share on other sites
quote:
Original post by smokes
Onnel:
what is the difference between pressed and down?!?

sleekgeekfreak:
You couldn''t explain to me what a debouncer is? and how it works?


Pressed is when you hit the key then release it (as though you are typing text). Down is simply held down at the instant you poll it.

Mike

Share this post


Link to post
Share on other sites
I solved it this way.. the function only returns true when a key has been released. As far as I can see the debouncer is just a way of checking the input every N'th frame.. I don't think that is a good approach because input would feel slow and unstable.. tried it first :-)



    
WORD OldKey=0;

bool IsKeyReleased(WORD Key)
{
if( !(Keystate[key] & 0x80) && (key == OldKey) )
{
OldKey = 0;
return true;
}
if( Keystate[key] & 0x80 )
OldKey = key;
return false;
}


Keystate is the buffer returned by GetDeviceState() which is called every frame.. hmm seems I shouldn't have started this tread at all.. no real problem.. sorry but I am a bit tired and first thought of it as a problem :-)

[edited by - Smokes on October 16, 2002 9:33:44 AM]

Share this post


Link to post
Share on other sites
Another method could be to record the current game frame for a particular key when it is pressed, then only add the letter to your console if the current game frame == frame that key was pressed. So if the user presses 'A' and the current frame is 1782, you just check to see if it is still frame 1782 (or 1783, depending on how you code your engine) before you process whatever it is that the 'A' key does.

I have been using this logic lately with various things, but for a while I was using the same methods as onnel and sleekgeekfreak. In my logic, a key that is 'pressed' is one that is being physically held down by someone's finger on a physical keyboard. A key that is 'down' is one that is both being pressed by the player and 'ready' to have input processed. So if I only want a key to do something once per press (as opposed to every frame that the key is 'pressed'), I make sure that the key is 'ready' and 'pressed'.

Psuedocode Example:


    
OnKeyPress(Key KeyThatHasBeenPressed)
{
if( KeyThatHasBeenPressed is 'ready' )
{
KeyThatHasBeenPressed is 'down'
KeyThatHasBeenPressed is no longer 'ready'
}
else
KeyThatHasBeenPressed is not 'down'

if(KeyThatHasBeenPressed is 'down')
ProcessLogicForKeyPress();
}


Hope that helps!

-Mike

[edited by - doctorsixstring on October 16, 2002 9:37:29 AM]

Share this post


Link to post
Share on other sites
Doctorsixstring:
Not to offend you but that approach seems like overkill compared to mine.. I mean all the logic is in the function I wrote.. much simpler.. but then again.. I can only get on keypress at a time using this method.. but this is okay for a console.. but perhaps it will bother me later *lol*

Share this post


Link to post
Share on other sites
No offense taken! Actually, I stand by my code . With the (very basic) logic that I gave, you don't ever have to bother calling a function when a key is released and you can have as many keys being pressed at the same time as your computer/OS allows (due to the fact that I keep track of every key individually in an array of keys). Basically, if a key is being pressed and it wasn't pressed previously (i.e. it is 'ready') then the code can go ahead and process whatever it is you want the key to do.

Also, if you only test for input when a key is released, your input will probably feel somewhat odd. Just try typing in a text editor or here on gamedev: letters are placed in the edit box as soon as you tap the key - they don't wait until you release the key.

And just to avoid confusion, the method I mentioned in my first paragraph is not related in any way to the logic I described in my second paragraph.

-Mike

[edited by - doctorsixstring on October 16, 2002 9:47:42 AM]

Share this post


Link to post
Share on other sites
you are right.. It would feel kindda stupid :-).. didn''t thought about that.. Now I''ve implemented something similar. thank you :-)

Share this post


Link to post
Share on other sites
I had the same problem. Someone pointed me to a similar solution. It worked alot better than my timing one where I only allowed keydown to be processed every 0.1 seconds or whatever.

Basically I have an array of 256 bools, one for each key that is being updated by my input.update() function. The key''s bool is true when it is pressed and false when it is not. Then in my code where I check for keydown I also have a bool that indicates whether the key was down last frame or not. If it was down last frame too, then I ignore the keydown this frame, if it was not down last frame then this is a new keydown event and I act on it. I think I will be moving the "keydown last frame" bool into my array so that my array has two bools for each key, one for down this frame and one for down last frame. This will allow me to check for "first time down", "still down", "first time up" and so on.

Basically the code looks like this
m_pInput->Update();
if((m_pInput->diks_thisframe[DIKS_RETURN] == TRUE) && (m_pInput->diks_lastframe[DIKS_RETURN] == FALSE)
{
//Do whatever I want done when Return is pressed
}


void CInput::Update()
{
for(int i = 0; i < 256; i++)
{
diks_lastframe = diks_thisframe[i];
//Get all key states and update diks_thisframe[]
...
}
}

Share this post


Link to post
Share on other sites