|
From: <ms...@mo...> - 2002-12-20 02:21:37
|
Patch against current CVS code for missed key stroke bug.
========
The current input routines keep track the Pressed/Not Pressed state of
all keys on the keyboard (using function ProcessKeyboardEvent, with
array KeyboardDown). The main loops inside the game core periodically
poll all of the keys they have an interest in to see if a key is currently
pressed (using function KeyDown).
The buttons states are checked something between 5 and 20 times a second.
Since the code only cares about what the state is 'right now', it is very
likely that a quick key tap will be completely missed by the game. This
leads to things like selecting a menu item not, or tapping the movement
keys having no effect. If you don't like repeating yourself a bunch,
this can be extremely irritating to try and use.
The following set of patches are just bandaids which fix the 'missed
keystroke problem'. They work by introducing the idea of 'pressed since
we last polled the key but not pressed now'... when a key is polled it
will return 'is pressed' if the key is either currently held down or
if the key has been tapped and released since the poll happened.
It does this by storing 0x1 in the KeyboardDown array for any key
currently held down, and 0x2 for any key that was pressed since last
check. 0x2 gets cleared every time KeyDown returns true. 0x1 gets
cleared anytime the key is released.
I have been using this code for about the last 24 hours and it seems to
work very well.
I hear that slayne is planning to rewrite the input handling routines from
scratch to correct this and a number of other issues like switching
polling input to input queue, adding/fixing support for joysticks, and
support for configurable key mappings ('x' == fire, '5' == 'select', etc).
Since the input system is to be overhauled, there appeared to be little
interest in this on IRC. I figured I would send it here for archive
purposes...
TTFN,
Mike
ps:
it would have been hundreds of lines shorter if the original case
statement didn't have a bazillion returns in it... sigh.
Index: sc2/src/sc2code/libs/input/sdl/input.c
===================================================================
RCS file: /cvsroot/sc2/sc2/src/sc2code/libs/input/sdl/input.c,v
retrieving revision 1.7
diff -u -p -r1.7 input.c
--- sc2/src/sc2code/libs/input/sdl/input.c 6 Dec 2002 17:49:15 -0000 1.7
+++ sc2/src/sc2code/libs/input/sdl/input.c 20 Dec 2002 01:58:59 -0000
@@ -113,11 +113,11 @@ ProcessKeyboardEvent(const SDL_Event *Ev
if (kbdtail == kbdhead)
kbdhead = (kbdhead + 1) & (KBDBUFSIZE - 1);
}
- KeyboardDown[Event->key.keysym.sym]=TRUE;
+ KeyboardDown[Event->key.keysym.sym] = 3;
}
else
{
- KeyboardDown[Event->key.keysym.sym]=FALSE;
+ KeyboardDown[Event->key.keysym.sym] &= 2;
}
}
}
@@ -408,111 +410,107 @@ KeyHit () // Does this clear the top of
//Status: Unimplemented
int
-KeyDown (UNICODE which_scan)
+KeyDown (UNICODE i)
// This might use SK_* stuff, of just plain old chars
{
- int i;
+ int which_scan = i;
+ int alt_scan = 0;
- i = which_scan;
- if (i == '\n')
+ switch (which_scan)
{
- if (KeyboardDown[SDLK_KP_ENTER])
- return (1);
- i = SDLK_RETURN;
- }
- else if (i >= 128)
- {
- switch (i)
- {
- case SK_LF_ARROW:
- if (KeyboardDown[SDLK_KP4])
- return (1);
- i = SDLK_LEFT;
- break;
- case SK_RT_ARROW:
- if (KeyboardDown[SDLK_KP6])
- return (1);
- i = SDLK_RIGHT;
- break;
- case SK_UP_ARROW:
- if (KeyboardDown[SDLK_KP8])
- return (1);
- i = SDLK_UP;
- break;
- case SK_DN_ARROW:
- if (KeyboardDown[SDLK_KP2])
- return (1);
- i = SDLK_DOWN;
- break;
- case SK_HOME:
- if (KeyboardDown[SDLK_KP7])
- return (1);
- i = SDLK_HOME;
- break;
- case SK_PAGE_UP:
- if (KeyboardDown[SDLK_KP9])
- return (1);
- i = SDLK_PAGEUP;
- break;
- case SK_END:
- if (KeyboardDown[SDLK_KP1])
- return (1);
- i = SDLK_END;
- break;
- case SK_PAGE_DOWN:
- if (KeyboardDown[SDLK_KP3])
- return (1);
- i = SDLK_PAGEDOWN;
- break;
- case SK_INSERT:
- if (KeyboardDown[SDLK_KP0])
- return (1);
- i = SDLK_INSERT;
- break;
- case SK_DELETE:
- if (KeyboardDown[SDLK_KP_PERIOD])
- return (1);
- i = SDLK_DELETE;
- break;
- case SK_KEYPAD_PLUS:
- i = SDLK_KP_PLUS;
- break;
- case SK_KEYPAD_MINUS:
- i = SDLK_KP_MINUS;
- break;
- case SK_LF_SHIFT:
- i = SDLK_LSHIFT;
- break;
- case SK_RT_SHIFT:
- i = SDLK_RSHIFT;
- break;
- case SK_CTL:
- if (KeyboardDown[SDLK_LCTRL])
- return (1);
- i = SDLK_RCTRL;
- break;
- case SK_ALT:
- if (KeyboardDown[SDLK_LALT])
- return (1);
- i = SDLK_RALT;
- break;
- case SK_F1:
- case SK_F2:
- case SK_F3:
- case SK_F4:
- case SK_F5:
- case SK_F6:
- case SK_F7:
- case SK_F8:
- case SK_F9:
- case SK_F10:
- case SK_F11:
- case SK_F12:
- i = (i - SK_F1) + SDLK_F1;
- }
+ case '\n' :
+ which_scan = SDLK_KP_ENTER;
+ alt_scan = SDLK_RETURN;
+ break;
+ case SK_LF_ARROW :
+ which_scan = SDLK_KP4;
+ alt_scan = SDLK_LEFT;
+ break;
+ case SK_RT_ARROW:
+ which_scan = SDLK_KP6;
+ alt_scan = SDLK_RIGHT;
+ break;
+ case SK_UP_ARROW:
+ which_scan = SDLK_KP8;
+ alt_scan = SDLK_UP;
+ break;
+ case SK_DN_ARROW:
+ which_scan = SDLK_KP2;
+ alt_scan = SDLK_DOWN;
+ break;
+ case SK_HOME:
+ which_scan = SDLK_KP7;
+ alt_scan = SDLK_HOME;
+ break;
+ case SK_PAGE_UP:
+ which_scan = SDLK_KP9;
+ alt_scan = SDLK_PAGEUP;
+ break;
+ case SK_END:
+ which_scan = SDLK_KP1;
+ alt_scan = SDLK_END;
+ break;
+ case SK_PAGE_DOWN:
+ which_scan = SDLK_KP3;
+ alt_scan = SDLK_PAGEDOWN;
+ break;
+ case SK_INSERT:
+ which_scan = SDLK_KP0;
+ alt_scan = SDLK_INSERT;
+ break;
+ case SK_DELETE:
+ which_scan = SDLK_KP_PERIOD;
+ alt_scan = SDLK_DELETE;
+ break;
+ case SK_KEYPAD_PLUS:
+ which_scan = SDLK_KP_PLUS;
+ break;
+ case SK_KEYPAD_MINUS:
+ which_scan = SDLK_KP_MINUS;
+ break;
+ case SK_LF_SHIFT:
+ which_scan = SDLK_LSHIFT;
+ break;
+ case SK_RT_SHIFT:
+ which_scan = SDLK_RSHIFT;
+ break;
+ case SK_CTL:
+ which_scan = SDLK_RCTRL;
+ alt_scan = SDLK_LCTRL;
+ break;
+ case SK_ALT:
+ alt_scan = SDLK_LALT;
+ which_scan = SDLK_RALT;
+ break;
+ case SK_F1:
+ case SK_F2:
+ case SK_F3:
+ case SK_F4:
+ case SK_F5:
+ case SK_F6:
+ case SK_F7:
+ case SK_F8:
+ case SK_F9:
+ case SK_F10:
+ case SK_F11:
+ case SK_F12:
+ which_scan = (which_scan - SK_F1) + SDLK_F1;
+ }
+
+ if (KeyboardDown[which_scan])
+ {
+ KeyboardDown[which_scan] &= 1;
+ return 1;
}
- return (KeyboardDown[i]);
+ if (alt_scan)
+ if (KeyboardDown[alt_scan])
+ {
+ KeyboardDown[alt_scan] &= 1;
+ return 1;
+ }
+
+ return 0;
}
INPUT_STATE
@@ -529,7 +527,10 @@ AnyButtonPress (BOOLEAN DetectSpecial)
for (i = 0; i < sizeof (KeyboardDown) / sizeof (KeyboardDown[0]); ++i)
{
if (KeyboardDown[i])
+ {
+ KeyboardDown[i] &= 1;
return (DEVICE_BUTTON1);
+ }
}
#if 0
for (i = 0; i < JOYSTICKS_AVAIL; i++)
|