4
\$\begingroup\$

I just want to ask if can I check for "KEY"(keyboard) that is HOLD/PRESSED for a long time, because I am to create a clone of breakout with air hockey for 2 different human players. Here's the list of my concern:

  1. Do I need other/ 3rd party library for KEY HOLDS?

  2. Is multi-threading needed? I don't know anything about this multi-threading stuff and I don't think about using one(I'm just a NEWBIE).

  3. One more thing, what if the two players pressed their respective key at the same time, how can I program to avoid error or worse one player's key is prioritized first before the the key of the other. example:

Player 1 = W for UP & S for DOWN Player 2 = O for UP & L for DOWN

(example: W & L is pressed at the same time)

PS: I use GLUT for the visuals of the game.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for breaking up your question. The site format generally prefers you to ask each individual question, because this is more helpful to potential future answer-seekers than a question titled by your very specific situation. (That is, direct, single, general questions have long term use.) \$\endgroup\$
    – Engineer
    Oct 29, 2012 at 12:25

4 Answers 4

7
\$\begingroup\$

You do not need a 3rd party library or multi-threading to detect long held keys. Depending on how you're doing it now, you're either going to be polling the keyboard to see what keys have been pressed or you're going to be responding to events when keys are pressed.

Either way, you're going to have a variable that keeps track of the exact time the key was pressed. Then, in your game loop you can see how long the key has been held just by checking currentTime - keyPressedTime. The difference will give you how long the key has been held.

Finally, while it's unlikely that players would press their keys at the exact same frame, this is possible if you're running slow or by chance. You can pick which player to process first by random choice. Simply generate a number of some MaxValue and if it's less than MaxValue/2 process player 1, otherwise process player 2.

\$\endgroup\$
0
4
\$\begingroup\$

Not sure it is perfect or exaсtly what you looking for and its for single-player, but try something like that (adapted from some books for newbies):

bool m_bPressedKeys[256];  // array of pressed keys current frame
bool m_bPressedKeysPrev[256]; // previous frame
bool m_bKeyLock[256];
float m_KeyDelayTimer(0.25f);
    float m_KeyRepeatTimer(0.01f);
GetINput()
{
    UCHAR pKeyBuffer[ 256 ];
    ZeroMemory( pKeyBuffer, sizeof( UCHAR ) * 256 );
    GetKeyboardState(pKeyBuffer); // Change this for non-Windows platforms
    memcpy(&m_bPressedKeysPrev, &m_bPressedKeys, sizeof(bool)*256);
    if (!(pKeyBuffer[i] & 0xF0))
    {
        m_bKeyLock[i] = false;
        m_bPressedKeys[i] = false;
    }
    else
    {
        m_bPressedKeys[i] = !(m_bKeyLock[i]);
    }
}


// You can use arrays OR accessors like this
bool KeyDown(const unsigned int& key)   const   { return ( m_bPressedKeys[key])&&(!m_bPressedKeysPrev[key]); }
bool KeyStillDown(const unsigned int& key) const { return ( m_bPressedKeys[key])&&( m_bPressedKeysPrev[key]); }
bool KeyUp(const unsigned int& key) const       { return (!m_bPressedKeys[key])&&( m_bPressedKeysPrev[key]); }
bool KeyStillUp(const unsigned int& key) const  { return (!m_bPressedKeys[key])&&(!m_bPressedKeysPrev[key]); }

// OR something more complicated:
bool IsKeyPressed( const int& key ) // returns true only once per press
{
    if ( KeyDown(key) )  // Simple check
    {
    LockKey(key); // Prevent key from pressing next frames until released
    return true;
    }
return false;
}

bool IsKeyPressedRepeatable( const int& key, const float& dt ) 
// "Tetris-style moving"
// returns true once, then after `KeyDelayTimer` seconds and repeats
// every `KeyDelayInterval` seconds (or your time units). 
// dt - is a delta time between game frames
{
if (KeyStillDown(key))
{
    m_KeyDelayTimer += dt;
    if (m_KeyDelayTimer >= m_KeyDelayInterval)
    {
        m_KeyRepeatTimer += dt;
        if ( m_KeyRepeatTimer >= m_KeyRepeatInterval )
        {
            m_KeyRepeatTimer -= m_KeyRepeatInterval;
            return true;
        }
    }

}
if (KeyDown(key))
{
    return true;
}
if (KeyUp(key))
{
    m_KeyDelayTimer = 0.0f;
}
return false;
}

Usage example:

if ( m_bPressedKeys['w'] ) // Just move player continuously every frame while key is pressed
{
    m_Player.Move( m_Player.GetSpeed() * dt, 0 ); // dx, dy
}

if ( m_bPressedKeys[VK_ESCAPE] ) // Go to menu once per press
{
    LockKey( VK_ESCAPE );
    m_Game->ChangeState(MenuState);
}

if ( IsKeyPressedOnce(VK_Space)) // Jump once per Spacebar press
{                                // Same as above, but cleaner
    m_Player->Jump();
}

if ( IsKeyPressedRepeatable(VK_LEFT, dt) ) // Move figure in Tetris.
{                                          // Second tick is delayed and
    m_Tetris->MoveFigureLeft();            // then repeating discretely
}

AFAIK not all keyboards supports multiple key presses at once or implement it not quite correctly. You must dig into it before coding.

\$\endgroup\$
0
0
\$\begingroup\$

Just use a timer. Have a Boolean that starts at false then when a key is pressed it makes it true. But also have when the key is not being pressed the Boolean is false. So when the timer reaches a certain number of milliseconds/time then have it do what you want... Hope this helps! :)

\$\endgroup\$
0
0
\$\begingroup\$
  1. You do not need a 3rd party library. You just need to be able to know if a key is held down or not.

  2. No multithreading is needed. Some libraries may use threading behind the scenes, but you do not have to create any threads for this.

  3. I don't believe you have much control over that.

Basically what you need to do is store the state of every key (held down or not), perhaps in an array. Every time you perform your update, record the current state if each key. Each key needs not just a Boolean of whether or not it is held down, but rather a positive number indicating how many successive frames that the key has been held (0 meaning the key is not held). By doing this, you can check to see how many frames a key has been held down, and customize your input to your liking. For example, you could only fire an action if a key press has a value of 1, and now that action will only fire the first time you press a key. Or fire an action whenever a key press value is greater then 0, meaning the action will be performed every update as long as the key is held down. You could even only perform an action after a key has been held for 10 frames. The feel of the input is up to you.

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .