Consecutive Key Presses: Difference between revisions
No edit summary |
Thunder4ik (talk | contribs) |
||
(8 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{Multiple issues| | |||
{{Dead end|date=January 2024}} | |||
{{Orphan|date=January 2024}} | |||
}} | |||
=Overview= | |||
Below is a proposition for a system to monitor | Below is a proposition for a system to monitor consecutive key presses within the Source engine. In the example provided, we'll monitor for two taps of the same key within a certain number of seconds. This system could be useful in a number of situations. One possible example would be a combo-based movement or combat system. | ||
=Our KeyTracker structure= | =Our KeyTracker structure= | ||
Line 8: | Line 13: | ||
<pre> | <pre> | ||
struct KeyTracker { | struct KeyTracker | ||
{ | |||
int flag; | int flag; | ||
Line 18: | Line 24: | ||
=Checking for key presses= | =Checking for key presses= | ||
I suggest creating a simple HandleKeyPress method which would be triggered in various circumstances. | I suggest creating a simple HandleKeyPress method which would be triggered in various circumstances. | ||
<pre> | <pre> | ||
if( | if (m_afButtonPressed & IN_FORWARD) | ||
{ | |||
HandleKeyTap( 0 ); | |||
}</pre> | }</pre> | ||
Line 29: | Line 36: | ||
=Handling the key presses= | =Handling the key presses= | ||
The following code is relatively self-explanatory, If the key has never been pressed, we set its flag to 1. If the key has already been | The following code is relatively self-explanatory, If the key has never been pressed, we set its flag to 1. If the key has already been pressed, we check to see whether the player pressed the key fast enough for it to count as a 'combo' or 'double tap'. Otherwise, we set it back to 1. After each call to HandleKeyPress we set LastPressTime to record the time of the keypress. This is used later to check if a player was fast enough in pressing that particular key a second time. In the following example, they have a 5 second window. | ||
<pre> | <pre> | ||
void | void HandleKeyTap( int iKeyId ) | ||
{ | |||
if( !doubleTap[iKeyId].flag ) { | if( !doubleTap[iKeyId].flag ) | ||
{ | |||
doubleTap[iKeyId].flag = 1; | doubleTap[iKeyId].flag = 1; | ||
} else if( doubleTap[iKeyId].flag > 0 && doubleTap[iKeyId].flag < 2 ) { | } | ||
else if( doubleTap[iKeyId].flag > 0 && doubleTap[iKeyId].flag < 2 ) | |||
{ | |||
// Check if the key was pressed fast enough to count as a double tap! | // Check if the key was pressed fast enough to count as a double tap! | ||
if( doubleTap[iKeyId].LastPressTime + 5.0f < gpGlobals->curtime ) { | if( doubleTap[iKeyId].LastPressTime + 5.0f < gpGlobals->curtime ) | ||
{ | |||
doubleTap[iKeyId].flag = 1; // Too slow! | doubleTap[iKeyId].flag = 1; // Too slow! | ||
} else { | } | ||
else | |||
{ | |||
doubleTap[iKeyId].flag = 2; // Double tap! | doubleTap[iKeyId].flag = 2; // Double tap! | ||
Line 51: | Line 65: | ||
} | } | ||
} else if( doubleTap[iKeyId].flag >= 2 ) { | } | ||
else if( doubleTap[iKeyId].flag >= 2 ) | |||
{ | |||
doubleTap[iKeyId].flag = 1; | doubleTap[iKeyId].flag = 1; | ||
Line 64: | Line 80: | ||
=Possible improvements= | =Possible improvements= | ||
The above solution is fairly primitive and, as such, can be updated and improved upon in a number of ways. Here are a few possible suggestions: | The above solution is fairly primitive and, as such, can be updated and improved upon in a number of ways. Here are a few possible suggestions: | ||
* | * Don't hard code the 'window' time value. Instead, set the value via a CON_COMMAND or a similarly flexible configuration routine. | ||
* Allocate the KeyTracker array in such a way as to avoid giving | * Allocate the KeyTracker array in such a way as to avoid giving particula r actions numeric ID's (in this example, pressing the IN_FORWARD key was assigned the value 0). Instead, it would be far better to map thearray to keys themselves. | ||
[[Category:Programming]] |
Latest revision as of 08:51, 21 January 2024




January 2024

You can help by

January 2024
Overview
Below is a proposition for a system to monitor consecutive key presses within the Source engine. In the example provided, we'll monitor for two taps of the same key within a certain number of seconds. This system could be useful in a number of situations. One possible example would be a combo-based movement or combat system.
Our KeyTracker structure
First we define a structure to track various keypresses. For each key we record a flag (to monitor its state) and the LastPressTime, which is relatively self-explanatory. As far as the flag value is concerned: 0 represents the key having never been pressed. 1 represents one press and 2 represents two presses.
struct KeyTracker { int flag; float LastPressTime; } doubleTap[ 2 ];
Checking for key presses
I suggest creating a simple HandleKeyPress method which would be triggered in various circumstances.
if (m_afButtonPressed & IN_FORWARD) { HandleKeyTap( 0 ); }
Handling the key presses
The following code is relatively self-explanatory, If the key has never been pressed, we set its flag to 1. If the key has already been pressed, we check to see whether the player pressed the key fast enough for it to count as a 'combo' or 'double tap'. Otherwise, we set it back to 1. After each call to HandleKeyPress we set LastPressTime to record the time of the keypress. This is used later to check if a player was fast enough in pressing that particular key a second time. In the following example, they have a 5 second window.
void HandleKeyTap( int iKeyId ) { if( !doubleTap[iKeyId].flag ) { doubleTap[iKeyId].flag = 1; } else if( doubleTap[iKeyId].flag > 0 && doubleTap[iKeyId].flag < 2 ) { // Check if the key was pressed fast enough to count as a double tap! if( doubleTap[iKeyId].LastPressTime + 5.0f < gpGlobals->curtime ) { doubleTap[iKeyId].flag = 1; // Too slow! } else { doubleTap[iKeyId].flag = 2; // Double tap! } } else if( doubleTap[iKeyId].flag >= 2 ) { doubleTap[iKeyId].flag = 1; } doubleTap[iKeyId].LastPressTime = gpGlobals->curtime; }
Possible improvements
The above solution is fairly primitive and, as such, can be updated and improved upon in a number of ways. Here are a few possible suggestions:
- Don't hard code the 'window' time value. Instead, set the value via a CON_COMMAND or a similarly flexible configuration routine.
- Allocate the KeyTracker array in such a way as to avoid giving particula r actions numeric ID's (in this example, pressing the IN_FORWARD key was assigned the value 0). Instead, it would be far better to map thearray to keys themselves.