How can I disable multiple keystrokes using GLUT? (Already googled for this and nothing working comes up).

Started by
1 comment, last by Chrono1081 12 years, 11 months ago
Hi guys,

I have an OpenGL program that uses GLUT however I need a way to prevent multiple keystrokes. I searched for this and found the function:

glutIgnoreKeyRepeat(int ignore);

but it doesn't seem to do anything and every single page I've searched for shows the exact same description. Is there a certain place I put this thing? I've tried everywhere and I've set the ignore variable to a non-zero value but still nothing works. Any help would be greatly appreciated.

What I'm trying to do is have it so if I press C, it doesn't keep "pressing" as long as I hold it in.

I included my code (its basic) just incase the way I was doing the key presses was a factor. I was using the tutorials on this site to enable detection of multiple keypresses: http://www.swiftless.com/

Here is my code: (Sorry for not using code tags, they don't work for me and just jumble the code sad.gif

[color="#008d12"]/* Includes for Mac OSX

[color="#008d12"]#include <GLUT/glut.h>

[color="#008d12"]#include <OpenGL/gl.h>

[color="#008d12"]#include <OpenGL/glu.h>*/



[color="#008d12"]//Includes for Windows

[color="#b3251e"][color="#0044fc"]#include <GL/glew.h>

[color="#b3251e"][color="#0044fc"]#include <GL/glut.h>

[color="#b3251e"][color="#0044fc"]#include <GL/freeglut.h>

[color="#b3251e"][color="#0044fc"]#include <iostream>



[color="#008d12"]//Arrays for key presses

[color="#0044fc"]bool* keyStates = [color="#0044fc"]new [color="#0044fc"]bool[256]; [color="#008d12"]//Regular keys

[color="#0044fc"]bool* keySpecialStates = [color="#0044fc"]new [color="#0044fc"]bool[256]; [color="#008d12"]//Special keys



[color="#008d12"]//Globals for objects

[color="#0044fc"]float angle = 0;




[color="#008d12"]//Globals for menu options

[color="#0044fc"]bool cullingEnabled = [color="#0044fc"]false;




[color="#008d12"]//======================================================================

[color="#008d12"]// Functions to manage windows and input

[color="#008d12"]//======================================================================



[color="#008d12"]//Timer function

[color="#0044fc"]void timer([color="#0044fc"]int iUnused)

{

glutPostRedisplay();

glutTimerFunc(30, timer, 0);

}




[color="#008d12"]//Function to handle character key down events

[color="#0044fc"]void keyDown([color="#0044fc"]unsigned [color="#0044fc"]char key, [color="#0044fc"]int x, [color="#0044fc"]int y)

{

[color="#008d12"] //Set key to 'pressed'

keyStates[key] = [color="#0044fc"]true;

}




[color="#008d12"]//Function to handle key up events

[color="#0044fc"]void[color="#000000"] keyUp(unsigned char[color="#000000"] key, int[color="#000000"] x, int[color="#000000"] y)

{

[color="#008d12"] //Set key to 'not pressed'

keyStates[key] = [color="#0044fc"]false;

}




[color="#008d12"]//Function to handle special key down events

[color="#0044fc"]void keySpecialDown([color="#0044fc"]int key, [color="#0044fc"]int x, [color="#0044fc"]int y)

{

[color="#008d12"] //Set key to 'pressed'

keySpecialStates[key] = 1;

}




[color="#008d12"]//Function to handle special key up events

[color="#0044fc"]void keySpecialUp([color="#0044fc"]int key, [color="#0044fc"]int x, [color="#0044fc"]int y)

{

[color="#008d12"] //Set key to 'not pressed'

keySpecialStates[key] = 0;

}




[color="#008d12"]//Function to control what happens on key state changes for regular keys

[color="#0044fc"]void keyOperations([color="#0044fc"]void)

{

[color="#008d12"] //These can obviously be changed and added to to provide UI functionality

[color="#0044fc"]if(keyStates[[color="#b3251e"]'a']) {printf([color="#b3251e"]"A is pressed.\n");}



[color="#0044fc"]if(keyStates[[color="#b3251e"]'b']) {printf([color="#b3251e"]"B is pressed.\n");}




[color="#0044fc"]if(keyStates[[color="#b3251e"]'c'])

{

[color="#b3251e"][color="#000000"] printf("C WAS PRESSED"[color="#000000"]);

[color="#0044fc"]if(!cullingEnabled)

{

[color="#b3251e"][color="#000000"] printf("CULLING IS ENABLED"[color="#000000"]);

glEnable(GL_CULL_FACE);

cullingEnabled = [color="#0044fc"]true;

}




[color="#0044fc"][color="#000000"] else

{

[color="#b3251e"][color="#000000"] printf("CULLING IS DISABLED"[color="#000000"]);

glDisable(GL_CULL_FACE);

cullingEnabled = [color="#0044fc"]false;

}

}




[color="#008d12"][color="#000000"] //...etc

}




[color="#008d12"]//Function to control what happens on special key state changes

[color="#0044fc"]void keySpecialOperations([color="#0044fc"]void)

{

[color="#008d12"] //These can obviously be changed and added to to provide UI functionality

[color="#0044fc"]if(keySpecialStates[GLUT_KEY_LEFT]) {printf([color="#b3251e"]"The Left Key was pressed.\n");}



[color="#0044fc"]if(keySpecialStates[GLUT_KEY_RIGHT]) {printf([color="#b3251e"]"The Right Key was pressed.\n");}



[color="#0044fc"]if(keySpecialStates[GLUT_KEY_UP]) {printf([color="#b3251e"]"The Up Key was pressed.\n");}



[color="#0044fc"]if(keySpecialStates[GLUT_KEY_DOWN]) {printf([color="#b3251e"]"The Down Key was pressed.\n");}

}




[color="#008d12"]//Function to draw the scene

[color="#0044fc"]void display([color="#0044fc"]void)

{

[color="#008d12"] //Check for key operations each frame to avoid multiple keypresses per frame

keyOperations();

keySpecialOperations();



[color="#008d12"] //Handle drawing

glClearColor(0.0f, 0.0f, 0.0f, 1.0f); [color="#008d12"]//Clear background of window

glClear(GL_COLOR_BUFFER_BIT); [color="#008d12"]//Clear the color buffer

[color="#008d12"][color="#000000"] glLoadIdentity(); //Load identity matrix to reset drawing locations



[color="#008d12"] //Translate scene back

glTranslatef(0.0f, 0.0f, -6.0f);



[color="#008d12"] //Draw a triangle

glPushMatrix();

glRotatef(angle, 0.0, 1.0, 0.0);

glBegin(GL_TRIANGLES);

[color="#008d12"][color="#000000"] //Front side

glColor3f(1.0f,0.0f,0.0f); [color="#008d12"]// Red

glVertex3f( 0.0f, 1.0f, 0.0f); [color="#008d12"]// Top Of Triangle (Front)

glColor3f(0.0f,1.0f,0.0f); [color="#008d12"]// Green

glVertex3f(-1.0f,-1.0f, 1.0f); [color="#008d12"]// Left Of Triangle (Front)

glColor3f(0.0f,0.0f,1.0f); [color="#008d12"]// Blue

glVertex3f( 1.0f,-1.0f, 1.0f); [color="#008d12"]// Right Of Triangle (Front)



[color="#008d12"][color="#000000"] //Right side

glColor3f(1.0f,0.0f,0.0f); [color="#008d12"]// Red

glVertex3f( 0.0f, 1.0f, 0.0f); [color="#008d12"]// Top Of Triangle (Right)

glColor3f(0.0f,0.0f,1.0f); [color="#008d12"]// Blue

glVertex3f( 1.0f,-1.0f, 1.0f); [color="#008d12"]// Left Of Triangle (Right)

glColor3f(0.0f,1.0f,0.0f); [color="#008d12"]// Green

glVertex3f( 1.0f,-1.0f, -1.0f); [color="#008d12"]// Right Of Triangle (Right)



[color="#008d12"][color="#000000"] //Back side

glColor3f(1.0f,0.0f,0.0f); [color="#008d12"]// Red

glVertex3f( 0.0f, 1.0f, 0.0f); [color="#008d12"]// Top Of Triangle (Back)

glColor3f(0.0f,1.0f,0.0f); [color="#008d12"]// Green

glVertex3f( 1.0f,-1.0f, -1.0f); [color="#008d12"]// Left Of Triangle (Back)

glColor3f(0.0f,0.0f,1.0f); [color="#008d12"]// Blue

glVertex3f(-1.0f,-1.0f, -1.0f); [color="#008d12"]// Right Of Triangle (Back)



[color="#008d12"][color="#000000"] //Left side

glColor3f(1.0f,0.0f,0.0f); [color="#008d12"]// Red

glVertex3f( 0.0f, 1.0f, 0.0f); [color="#008d12"]// Top Of Triangle (Left)

glColor3f(0.0f,0.0f,1.0f); [color="#008d12"]// Blue

glVertex3f(-1.0f,-1.0f,-1.0f); [color="#008d12"]// Left Of Triangle (Left)

glColor3f(0.0f,1.0f,0.0f); [color="#008d12"]// Green

glVertex3f(-1.0f,-1.0f, 1.0f); [color="#008d12"]// Right Of Triangle (Left)

glEnd();

glPopMatrix();



[color="#008d12"][color="#000000"] glutSwapBuffers(); //Flush buffers to the window



[color="#008d12"][color="#000000"] angle++; //Rotation angle for pyramid

}




[color="#008d12"]//Function to reshape the window when dragged

[color="#0044fc"]void reshape([color="#0044fc"]int width, [color="#0044fc"]int height)

{

[color="#008d12"] //Set viewport to window size

glViewport(0, 0, (GLsizei)width, (GLsizei)height);



[color="#008d12"] // Switch to projection matrix to manipulate how scene is viewed

glMatrixMode(GL_PROJECTION);

[color="#008d12"][color="#000000"] glLoadIdentity(); //Reset projection matrix to avoid artifacts



[color="#008d12"] //Set FOV, + Near and Far clip planes

gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0);



[color="#008d12"] //Switch back to modelview matrix

glMatrixMode(GL_MODELVIEW);

}

[color="#008d12"]//----------------------------------------------------------------------



[color="#008d12"]//======================================================================

[color="#008d12"]// Main Function

[color="#008d12"]//======================================================================

[color="#0044fc"]int main([color="#0044fc"]int argc, [color="#0044fc"]char** argv)

{

glutInit(&argc, argv); [color="#008d12"]//Initialize GLUT



[color="#008d12"] //Initialize key state arrays

[color="#0044fc"]for([color="#0044fc"]int i = 0; i < 256; ++i)

{

keyStates = [color="#0044fc"]false;

keySpecialStates = [color="#0044fc"]false;

}



[color="#008d12"] //Set display properties

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); [color="#008d12"]//Set up a basic display buffer

[color="#008d12"][color="#000000"] glutInitWindowSize(1000, 1000); //Set the width and height of the window

glutInitWindowPosition(100, 100); [color="#008d12"]//Set window position

glutCreateWindow([color="#b3251e"]"GSP 420"); [color="#008d12"]//Set window caption



[color="#008d12"] //Window Control Functions

[color="#008d12"][color="#000000"] glutDisplayFunc(display); //Tell glut to draw window based on function

[color="#008d12"][color="#000000"] glutReshapeFunc(reshape); //Tell glut to reshape the window when dragged



[color="#008d12"] //Keyboard Control Functions

[color="#008d12"][color="#000000"] glutKeyboardFunc(keyDown); //Tell glut to use keyDown function to handle key presses

[color="#008d12"][color="#000000"] glutKeyboardUpFunc(keyUp); //Tell glut to use keyUp function to handle key releases



[color="#008d12"][color="#000000"] glutSpecialFunc(keySpecialDown); //Tell glut to use keySpecialDown function to handle special key events

[color="#008d12"][color="#000000"] glutSpecialUpFunc(keySpecialUp); //Tell glut to use keySpecialUp function to handle special key up events






[color="#008d12"][color="#000000"] //Timer to control framerate

timer(0);




[color="#008d12"] //Glutloop to keep program running

glutMainLoop();





[color="#0044fc"][color="#000000"] return[color="#000000"] 0;

}

Advertisement
The issue you're seeing is due to the fact that you run keyOperations() every frame, and that keyStates['c'] is set to true from the moment the key is pressed (keydown event) to the moment the key is released (keyup event). If you're running at 60 FPS, for every 60th of a second that the key is pressed down, the code will run; you're bound to get a lot of duplicate key presses regardless of whether key-repeat is ignored or not...

To avoid this, usually you'll want to make it so that the keyup event calls the function (since it's usually guaranteed to be unique, repeat enabled or not). You could also keep another array that keeps track of whether or not the keypress is a "first press" or not. Or you could simply set keyStates['c'] to false after you've processed it (in that case, you'll want to use glutIgnoreKeyRepeat so it doesn't get set back to true when an additional keydown is received).

The issue you're seeing is due to the fact that you run keyOperations() every frame, and that keyStates['c'] is set to true from the moment the key is pressed (keydown event) to the moment the key is released (keyup event). If you're running at 60 FPS, for every 60th of a second that the key is pressed down, the code will run; you're bound to get a lot of duplicate key presses regardless of whether key-repeat is ignored or not...

To avoid this, usually you'll want to make it so that the keyup event calls the function (since it's usually guaranteed to be unique, repeat enabled or not). You could also keep another array that keeps track of whether or not the keypress is a "first press" or not. Or you could simply set keyStates['c'] to false after you've processed it (in that case, you'll want to use glutIgnoreKeyRepeat so it doesn't get set back to true when an additional keydown is received).



Thank you so much! It works perfectly!

This topic is closed to new replies.

Advertisement