How to detect multiple key presses in OpenGL?

Started by
4 comments, last by lordmonkey 13 years, 5 months ago
Hello everybody,
I am pretty new to OpenGL so please try to understand me :).
I have that beautiful function

void key(unsigned char k, int x, int y)

which is posted to OpenGL in :

glutKeyboardFunc(key);

but with this function I can only detect one key being pressed at a time. How can I do it to detect multiple key presses ?
Advertisement
Quote:Original post by lordmonkey
I am pretty new to OpenGL so please try to understand me :).
I have that beautiful function

void key(unsigned char k, int x, int y)

which is posted to OpenGL in :

glutKeyboardFunc(key);
Note that this is actually a question about Glut, which is only tangentially related to OpenGL. Regardless:
Quote:but with this function I can only detect one key being pressed at a time. How can I do it to detect multiple key presses ?
It will be called once each time a key is pressed. If you want to track multiple key presses, then each time the function is called, record which key was just pressed in an array (do the same with a keyup function to clear them). Then you can check the array to see all the keys which are pressed at the current time...

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

And just to add on be sure you read them in individual ifs and not a set of else if's otherwise it will find one key and return.
Ok, I have it working but i have 2 problems with this, but first i will explain what I implemented:

I have something like this to atore info about pressed keys :
enum key_state {NOTPUSHED, PUSHED} keyarr[127];

for my array of pushed or notpushed values for every key, then i will initialized them all with notpushed value

then:
this is my : glutKeyboardFunc(key);
void key(unsigned char k, int x, int y)
{
if(k == 'd')
keyarr[int('d')] = PUSHED;
if(k == 'w')
keyarr[int('w')] = PUSHED;
if(k == 'r')
keyarr[int('r')] = PUSHED;
glutPostRedisplay();
}

this is my : glutKeyboardUpFunc(keyup);
void keyup(unsigned char k, int x, int y)
{
if(k == 'd')
keyarr['d'] = NOTPUSHED;
if(k == 'w')
keyarr['w'] = NOTPUSHED;
if(k == 'r')
keyarr['r'] = NOTPUSHED;

glutPostRedisplay();
}

and in the main draw() function (for now i don't have any other place to put it in) I put :

if( keyarr['d'] )
tankTurretAngle--;
if( keyarr['w'] )
wheelAngle += 5;
if( keyarr['r'] )
yRot++;

and it works :) but...
1)when I press any key of defined ones there is this small 'lag' like in windows when you push and hold key while typing how can I omit that ?
2) when I release one of e.g. 3 held keys whole animation which is running thanks to that stops. how can I handle this so that the animation won't stop but only the part responsible for the released key ?
They keyboard functions are only called when you actually press or release a key, and consequently, glutPostRedisplay is only called when you actually press or release a key. You can actually get multiple key presses by holding the key down, but that is only because GLUT issues multiple callbacks if you hold it down, just like you can do in, say, notepad by holding down a key to "type" repeated keystrokes.

What you need instead is to only record the keys in the callback functions, and then use the idle callback to redisplay your scene. Thus, remove glutPostRedisplay from your keyboard callbacks, and set the idle callback like this:
void idle(){    glutPostRedisplay();}int main(){    ...    glutIdleFunc(idle);    ...}

The idle function is called as soon as there's nothing else to do (like handling keyboard messages), which you use to update your game logics and redisplaying the scene.
Hell yeah :) :] that works perfectly , thanks a lot.

This topic is closed to new replies.

Advertisement