• Advertisement
Sign in to follow this  

direct input - precisely, how does it work?

This topic is 2300 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

k, it's kind of a vague subject, but i think i need a better grasp of what direct input is actually doing at the knuts and bolts level to troubleshoot my issues. What i'm doing is trying to translate keypresses into asci characters like any normal keyboard should do, and i came up with this elaborate (another word for disorganized) solution.

I have a structure like so:



struct KeypressBuffer
{
unsigned long Keypress[94];
bool needShift[94];
bool wasPressed[94];
bool SpaceWasPressed;
bool CapsToggle;
bool capsWasPressed;
bool backWasPressed;
};


the keypresses and need shift are defined when it is initilized, and never change, like so:


int index = 1;

m_KeypressBuffer.Keypress[index] = DIK_1; // 33 !
m_KeypressBuffer.needShift[index] = true;
index++;

m_KeypressBuffer.Keypress[index] = DIK_APOSTROPHE; // 34 "
m_KeypressBuffer.needShift[index] = true;
index++;

m_KeypressBuffer.Keypress[index] = DIK_3; // 35 #
m_KeypressBuffer.needShift[index] = true;
index++;

m_KeypressBuffer.Keypress[index] = DIK_4; //36 $
m_KeypressBuffer.needShift[index] = true;
index++;

m_KeypressBuffer.Keypress[index] = DIK_5; //37 %
m_KeypressBuffer.needShift[index] = true;
index++;

m_KeypressBuffer.Keypress[index] = DIK_7; // 38 &
m_KeypressBuffer.needShift[index] = true;
index++;

m_KeypressBuffer.Keypress[index] = DIK_APOSTROPHE; // 39 '
m_KeypressBuffer.needShift[index] = false;
index++;


.....

And so on in order of their respective ascii character values. then i have a for loop that checks every frame like so:


for(int i = 1; i < 95; i++)
{
if( (m_Keypresses[ m_KeypressBuffer.Keypress ] & 0x80) && (!m_KeypressBuffer.wasPressed) && ( ( ( (m_Keypresses[DIK_LSHIFT] & 0x80) == m_KeypressBuffer.needShift) || ((m_Keypresses[DIK_RSHIFT] & 0x80) == m_KeypressBuffer.needShift) ) || (m_KeypressBuffer.CapsToggle == m_KeypressBuffer.needShift)))
{
m_intext[len] = i+32;
m_intext[len + 1] = '\0';
m_KeypressBuffer.wasPressed = true;
}
if( !(m_Keypresses[m_KeypressBuffer.Keypress] & 0x80) && (m_KeypressBuffer.wasPressed))
{
m_KeypressBuffer.wasPressed = false;
}
}


which checks if it's pressed currently, if it wasn't pressed last frame, if the left or right shift is pressed and whether that character requires or doesn't require a shift key, and whether the caps lock is currently toggled. m_intext is a string, and what happens here is, it concatenates the letter onto the end of string if it meets all the conditions. then it says, for the next frame, that it was pressed. then on the next frame, if it's still held down, that if fails, and the next if fails and nothing happens. then the moment it's let go, the 'was pressed' marker for that respective key is still on so it fails the first check, but the second check succeeds, resetting it's 'was pressed' value, ready to take the input again. now, this works almost without a hitch, except that it is entirely ignoring the shift keys. i get these errors,

warning C4805: '==' : unsafe mix of type 'int' and type 'bool' in operation

which leads me to believe that i'm missing something. when direct input checks for the state of a key, does it not resolve to a boolean, and is the comparison faulty because of it? because when i initialize the array of constants at the beggining , you see that each individual character has a needshift value as a boolean, so in that massive if statement in the for loop there, it checks to see whether the keypress relates to whether that character needs shift. if it needs shift and it's not pressed, the character is ignored and not concatted and vice versa. if it doesn't need shift and it IS pressed, the character is ignored and vice versa. however, i don't think comparing the state of the shift key against a boolean is working here. does anyone have a better suggestion, or possibly a more foolproof way of doing what i wish to accomplish here?

for the record, it does successfully concatenate the correct characters that you press to the screen, it just doesn't add the upper case version when your pressing shift, it still just adds the lowercase.

Share this post


Link to post
Share on other sites
Advertisement

-long post-


basically it this line:

if( (m_Keypresses[ m_KeypressBuffer.Keypress ] & 0x80) && (!m_KeypressBuffer.wasPressed) && ( ( ( (m_Keypresses[DIK_LSHIFT] & 0x80) == m_KeypressBuffer.needShift) || ((m_Keypresses[DIK_RSHIFT] & 0x80) == m_KeypressBuffer.needShift) ) || (m_KeypressBuffer.CapsToggle == m_KeypressBuffer.needShift)))

you're basically doing:

if( (intValue) && (boolvalue) && ( ( ( (intValue) == boolValue) || ((intValue) == boolValue) ) || (boolValue == boolValue)))

The bolded parts are int->bool comparison which generates a warning.

the bool value will be implicitly cast/widened to an int, true becomes 1 and false 0.

The warning occurs because if you have an intValue which is different from 1 or 0 it will always be false. (Which most likely isn't what you intend)

This:
(m_Keypresses[DIK_LSHIFT] & 0x80) == m_KeypressBuffer.needShift) :
m_Keypresses[DIK_LSHIFT] & 0x80 can only be 0x80 (128) or 0 which means that if m_KeypressBuffer.needShift is true the only 2 results are:

0 == 1 (false)
128 == 1 (false)

Share this post


Link to post
Share on other sites
k i added a statement and a variable above the for loop like so:


if( (m_Keypresses[DIK_RSHIFT] &0x80) || (m_Keypresses[DIK_LSHIFT] & 0x80))
{
strcpy_s(m_outtext, "down");
shiftdown = true;
}
else if( !(m_Keypresses[DIK_RSHIFT] &0x80) && !(m_Keypresses[DIK_LSHIFT] & 0x80))
{
strcpy_s(m_outtext, "up");
shiftdown = false;
}


and then replaced the whole part involving shift in that if statement with:

(shiftdown == m_KeypressBuffer.needShift)

which fixed the warnings. now it looks like this:


if( (m_Keypresses[ m_KeypressBuffer.Keypress ] & 0x80) && (!m_KeypressBuffer.wasPressed) && ((shiftdown == m_KeypressBuffer.needShift) || (m_KeypressBuffer.CapsToggle == m_KeypressBuffer.needShift) ) )

that strcpy there is just to print on the screen whether it shows that it's pressed or not, and it does indeed toggle, but the capital letters still don't work :\ . any other ideas?

Share this post


Link to post
Share on other sites
k, i omitted the boolean at the end involving the caps lock, so now it's:

if( (m_Keypresses[ m_KeypressBuffer.Keypress ] & 0x80) && (!m_KeypressBuffer.wasPressed) && (shiftdown == m_KeypressBuffer.needShift))

and that works, so i guess i'll work with the caps lock later to see what's up. but now i'm faced with a new problem. so far, i've trusted that when all the keys are pressed, there state remains changed constantly until released, but apparently the space bar likes to flicker, which wholly screws up my method. this is run just below that for loop every frame:



if((m_Keypresses[DIK_SPACE] & 0x80) && !(m_KeypressBuffer.SpaceWasPressed))
{
m_intext[len] = ' ';
m_intext[len +1] = '\0';
m_KeypressBuffer.SpaceWasPressed = true;
}
else if ( !(m_Keypresses[DIK_SPACE] & 0x80) && (m_KeypressBuffer.SpaceWasPressed))
{
m_KeypressBuffer.SpaceWasPressed = false;
}



this does indeed add a space when the space bar is pressed, but it'll add a bunch of spaces, and continuously add them while it's held down. I have the backspace setup very similar and i have no problems with it whatsoever. It looks like this:



if( (m_Keypresses[DIK_BACK] & 0x80) && !(m_KeypressBuffer.backWasPressed))
{
m_intext[strlen(m_intext) - 1] = '\0';
m_intext[strlen(m_intext)] = 0;
m_KeypressBuffer.backWasPressed = true;
}
else if ( !(m_Keypresses[DIK_BACK] & 0x80) && (m_KeypressBuffer.backWasPressed) )
{
m_KeypressBuffer.backWasPressed = false;
}



can anyone think of a better solution to this? on pressing the space bar, i wish to add one and only one space to the end of a string until it is released and pressed again.

Share this post


Link to post
Share on other sites
Just my two cents, but direct input is considered obsolete these days. A much cleaner approach to solve any problem you are having, as well as enhance functionality, you should look into the Raw Input API. It is easy to use and much more powerful.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms645543%28v=vs.85%29.aspx#_win32_Registration_for_Raw_Input

Share this post


Link to post
Share on other sites
For text input, you should be handling WM_CHAR messages rather than translating key events from DirectInput/Raw Input yourself. This way you do not have to screw around with transforming characters when modifier keys such as Shift and Caps Lock are on, you get correct key delay/repeat behaviour and things are not going to blow up when somebody with a different keyboard layout tries to play your game.

DirectInput/Raw Input are fine to be used for your regular game input, but not for text (which from your provided code you appear to be trying to do).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement