I'm in the process of migrating a program from GLUT to SDL. In my current program pressing the a key results in a different response then pressing the A key. This was pretty straightforward to do in GLUT as it the keyboard function callback passed in the ASCII value of the key that was pressed.
void keyPressedFn(unsigned char key, int x, int y){
switch(key){
case 'a':
// do work for a
break;
case 'A':
// do work for A
break;
}
}
I'm struggling to replicate similar functionality in SDL as pressing the a key produces the same response regardless of if SHIFT or CAPS LOCK are pressed as well.
Is there a simple way of replicating the above function in SDL?
Edit: In the example above I only show how to handle one key, in practice however, I am going to have a list of about 15 keys that I want to respond to differently if the shift key is pressed as well.
Check the keyboard modifiers that are present when you get a keydown event. For example:
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_a)
{
if(event.key.keysym.mod & KMOD_SHIFT)
{
// Handle 'A'
}
else
{
// Handle 'a'
}
}
break;
...
}
}
SDL_keysym has mod field, which contains state of modifier keys at the time the event has been emitted. Bit-AND it with KMOD_SHIFT to check whether Shift has been active. See SDL wiki.
Why not just do this?
void keyPressedFn(unsigned char key, int x, int y){
switch(key){
case 'a':
case 'A':
// do work for A or a
break;
}
}
Do you have some other concerns that you cannot do as what I have suggested? If not I think this is as simple as it can get.
Related
I am using SDL2 in C++ to create a sprite. However, the SDL_KEYUP is constantly triggered when I am pressing the key.
void update() override {
if(Game::event.type == SDL_KEYDOWN) {
switch(Game::event.key.keysym.sym) {
case SDLK_z:
cout << "key down" << endl;
break;
default:
break;
}
}
if(Game::event.type == SDL_KEYUP) {
switch(Game::event.key.keysym.sym) {
case SDLK_z:
cout << "Key up" << endl;
break;
default:
break;
}
}
}
It's a feature, not a bug. If you hold a key for half a second or so, SDL will start to generate "fake" key-down & key-up events.
This is used primarily for text editing, but is mostly useless otherwise.
Ignore all keyboard events that have event.key.repeat != 0.
Also, if you're writing a game, you might want to use scancodes instead of keycodes (e.g. event.key.keysym.scancode == SDL_SCANCODE_A instead of event.key.keysym.sym == SDLK_a).
Keycodes depend on the current layout, and scancodes don't. Scancodes represent physical key locations. The diffence is noticeable if you use a non-QWERTY layout. (E.g. SDLK_z is always bound to the key that has Z printed on it, while SDL_SCANCODE_W is bound to W on QWERTY and Z on AZERTY.)
I'm trying to use the glut framework to handle keypresses for a game I'm writing in c++. When a specific key is pressed, I want to start drawing a new curve and so I create a new curve and add it to my container of curves. However, when I use onKeyboard and debug I see that this function is called over and over when a key is pressed, not just on the initial press. Therefore, it's creating about 12 curves every time a key is pressed. My code for onKeyboard is below. Any help would be appreciated greatly!
void onKeyboard(unsigned char key,int x, int y) {
keysPressed[key] = true;
switch (key) {
case 'l':
curvesContainer.addCurve(new lCurve());
break;
case 'p':
curvesContainer.addCurve(new pCurve());
}
glutPostRedisplay();
}
You would simply check if keyPressed[key] is already true, and only add your curve if it is false.
void onKeyboard(unsigned char key,int x, int y)
{
if (keysPressed[key] == false)
{
keysPressed[key] = true;
switch (key)
{
case 'l':
curvesContainer.addCurve(new lCurve());
break;
case 'p':
curvesContainer.addCurve(new pCurve());
break;
}
}
glutPostRedisplay();
}
You will additionally need to clear keysPressed[key] in an onKeyUp event, using glutKeyboardUpFunc
void onKeyUp(unsigned char key,int x, int y)
{
keysPressed[key] == false;
}
glutIgnoreKeyRepeat(1) is probably what you want. (1 = on)
Use input flush define in studio.in
It avoid rest of input
Here i am having function like this. problem i am facing while changing Set parameter section.
first: i could not able to change Set_parameter Window
Second: Since in my loop i am saying if none key pressed display clock.because of that when i enter into Section menu it directly bounce back to Main displaying clock. Is there any way, where i can stay menu section unless Exit/LEFT key pressed
This main function where i am calling my LCD_call Function
void loop()
{
int button;
while(( button = read_LCD_buttons()) != btnNONE)
{
lcd_call();digitalClockDisplay();
}
}
LCD_call being called here.
LCD_call
break command should break/exit the loop.
It could be that the if condition is not coming out to be true, for any input case.
Try debugging your code by placing a break point inside if.
if(button==btnSELECT)
{
break; // place your breakpoint here.
}
and check if your code satifies the if condition for any possible input.
This should work :
void lcd_call()
{
while ( (button = read_LCD_buttons()) != btnSELECT)
{
DS_Counter=Display_selection();
switch (DS_Counter)
{
case 1:
lcd.setCursor(0,0);
digitalClockDisplay();
timedBeep(shortBeep,1);
break;
case 2:
lcd.setCursor(0,0);
Display_angle();
timedBeep(shortBeep,1);
break;
case 3:
lcd.setCursor(0,0);
Display_coordinate();
timedBeep(shortBeep,1);
break;
case 4:
lcd.setCursor(0,0);
Display_Wind();
timedBeep(shortBeep,1);
break;
case 5:
break;
}
}
}
You have already given a condition in While loop. As soon as the condition is false, it will break the while loop
I'm using Freeglut to design some basic games. However, I have been having some issues with keyboard input.
In some previous games I made, I had did something like this: (pseudocode)
class Key {
bool pressed;
void press() {pressed = true;}
void release() {pressed = false;}
bool isPressed() {return pressed;}
}
Key wkey, skey;
handleKeypress(unsigned char key, int xf, int yf) { //This is the function that glutKeyBoardFunc gets
switch(key) {
case 'w':
wkey.press();
case 's':
skey.press();
}
}
handleKeypress(unsigned char key, int xf, int yf) { //This is the function that glutKeyBoardUpFunc gets
switch(key) {
case 'w':
wkey.release();
case 's':
skey.release();
}
}
When I wanted to check whether or not a key was pressed, I checked wkey.isPressed(). However, this caused issues. For example, the Esc key was supposed to pause the game, and then pressing Esc from the pause screen was supposed to take the user to the main menu. However, pressing Esc directly took the user to the main menu because the user didn't release the escape key in that tick of the main loop.
To avoid this kind of issue, what is the best way to take (and use) keyboard input with Freeglut?
EDIT: By the way, this is C++
How about you save a previous key state and a current key state for each frame? This way you can test if the previous key state was KEY UP and the new key state is KEY DOWN. This indicates that the key has been pressed. You can adopt this for a "key pressed" function - just test to see if the previous key state was KEY DOWN and the new key state is also KEY DOWN. A "key up" function would test if the previous key state was KEY DOWN and the new key state is KEY UP.
OS:: win xp sp3.
Qt:: 4.6
I have class Gameboard in which i have some rectangle.I defined keyPressEvent for that rectangle in order to move him around the screen.Key_A :: rectangle.moveToLeft & Key_D :: rectangle.moveToRight.Problem is that keys work with delay.
When i release one key and press another one it takes some time before that one begin to work.I checked Qt online documentation and now for that effect but dont now how to make those keys to work instantly without delay beetween them?
code snippet:
//in Gameboard class
ship = new QRect(x,y,w,h);
void Gameboard::keyPressEvent(QKeyEvent* event)
{
switch(event->key()) {
case Qt::Key_A :
{
x = x-10;
ship->moveTo(x,y);
break;
}
case Qt::Key_D :
{
x = x+10;
ship->moveTo(x,y);
break;
}
}
}
Put input cursor into any applicable text box and press the 'A' key. What you'll see is once you press the key, letter 'A' will be printed, then there will be a pause, and then first letter 'A' will be quickly followed by many others. That's the way keypress events work. And your program is receiving them exactly like this. First you receive one event when the key is actually pressed, and then after a delay you get a lot of automatically repeated events, in case user wants to enter one character many-many times.
It works perfectly for text input, but in games you usually need smooth movement. If that's the case, you need to move your ship not upon receiving the event, but regularly, for example, on timer event. And you will need to catch both keyPressEvent and keyRelease event and use them to remember what movement keys are currently pressed. So you could for example do this:
struct Ship {
bool is_moving_left, is_moving_right;
QPoint position;
int speed;
...
void timerEvent()
{
if (is_moving_left) position.setX (position.x() - speed);
if (is_moving_right) position.setX (position.x() + speed);
}
...
};
...
void Gameboard::keyPressEvent (OKeyEvent *_event)
{
switch(event->key()) {
case Qt::Key_A :
ship->is_moving_left = true;
break;
case Qt::Key_D :
ship->is_moving_right = true;
break;
}
}
...
void Gameboard::keyReleaseEvent (OKeyEvent *_event)
{
switch(event->key()) {
case Qt::Key_A :
ship->is_moving_left = false;
break;
case Qt::Key_D :
ship->is_moving_right = false;
break;
}
}
Then just make sure Ship::timerEvent() gets called on every timer event in the game.