🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

SDL unicode key input trouble

Started by
7 comments, last by Axenation 19 years, 9 months ago
I'm making a console (text input box) for my game, and, to make sure you can type all possible characters of the keyboard, including §, {, capitals with shift or caps lock, etc..., I use SDL_EnableUNICODE(1); and to check the key event asciiChar = event.key.keysym.unicode & 0x7F; There are, however, some problems with it: 1) First of all, the event sometimes returns things when I'm not pressing a key, most often ascii code 1 (which is a smiley character in my font). Where do these come from, and how do I prevent getting them? 2) The second thing is, if I press a key, this event just keeps returning the ascii character, so that if I try to type something, I get the letters lots of times in a row instead of just once! Is there a nice way to fix it, or do I have to make something myself that checks for every key if you weren't already holding it down? (very annoying to do because it has to be done separately for each key to be able to type fast, otherwise you have to release one key before you're able to press another key, and if you type fast you don't do that) 3) I use SDL events not only for this unicode stuff, but also for mouse input, to check when you close the program, for NON-unicode key input (it's a game so you need to press arrow keys and stuff), and more. Appearantly, if I poll the event separately for each of those actions, it sometimes misses the action, most notably: if you want to close the window, but you press the close butotn with your mouse while it was just polling an unicode event for example, then the window does NOT close, and the correct polling misses it. So, do I have to poll for events only ONCE, and use that one poll for everything, unicode input, mouse actions, closing the window, and so on? 4) Back to the unicode stuff, keys like Return, Escape, Backspace return ascii values too, and I'm just asking to be sure: are these ascii codes the same on all platforms? I want the enter key to do the same on linux as on windows of course, and checking it by usign this unicode value would be handy here. EDIT: found a 5th problem :( 5) In unicode, all keys are working, except the numpad! Numpad numbers and "/" symbol don't work, strangely, +, - and * are working. This is on a Belgian keyboard. Don't the numpad numbers generate unicode values? BTW I tried both with num lock on and off. [Edited by - Lode on October 9, 2004 5:01:33 PM]
Advertisement
Quote: Original post by Lode
2) The second thing is, if I press a key, this event just keeps returning the ascii character, so that if I try to type something, I get the letters lots of times in a row instead of just once! Is there a nice way to fix it, or do I have to make something myself that checks for every key if you weren't already holding it down? (very annoying to do because it has to be done separately for each key to be able to type fast, otherwise you have to release one key before you're able to press another key, and if you type fast you don't do that)


this is because your taking input too fast. the problem is, is that when you press a key, even just pressing this key once, you are probably holding down the key for about 1/10th of a second or something like that. the problem is, even at 30 FPS, this means pressing a key once will register the key being pressed 3 times. at 100 FPS the key would be pressed 10 times. this is just made up numbers, but you get the point. basically the loop is running multiple times while you are tapping that key...

to fix this, there are a number of ways... i had this exact problem when trying to get raw input.. i tried using timers, but for some reason that didn't work too well for me, so instead i check if the old key is == the new key.. pretty simple.

IE, do this:

if(key_pressed != old_key_pressed)
{
add this character to the string here
}


Quote:
3) I use SDL events not only for this unicode stuff, but also for mouse input, to check when you close the program, for NON-unicode key input (it's a game so you need to press arrow keys and stuff), and more. Appearantly, if I poll the event separately for each of those actions, it sometimes misses the action, most notably: if you want to close the window, but you press the close butotn with your mouse while it was just polling an unicode event for example, then the window does NOT close, and the correct polling misses it.
So, do I have to poll for events only ONCE, and use that one poll for everything, unicode input, mouse actions, closing the window, and so on?

yes, you should definetly NOT be polling for input for each seperate action. im not sure, but im pretty sure you should not poll more then once in a single game loop. this is just asking for trouble (missing input). poll in one spot. you can have a flag, like bool taking_raw_input. when this is set to true, then you can extract the raw input using event.key.keysym.unicode & 0x7F;... when its false, dont do that.. then, when the user wants to type something, just set this bool to true...
FTA, my 2D futuristic action MMORPG
Quote: Original post by graveyard filla
Quote: Original post by Lode
2) The second thing is, if I press a key, this event just keeps returning the ascii character, so that if I try to type something, I get the letters lots of times in a row instead of just once! Is there a nice way to fix it, or do I have to make something myself that checks for every key if you weren't already holding it down? (very annoying to do because it has to be done separately for each key to be able to type fast, otherwise you have to release one key before you're able to press another key, and if you type fast you don't do that)


this is because your taking input too fast. the problem is, is that when you press a key, even just pressing this key once, you are probably holding down the key for about 1/10th of a second or something like that. the problem is, even at 30 FPS, this means pressing a key once will register the key being pressed 3 times. at 100 FPS the key would be pressed 10 times. this is just made up numbers, but you get the point. basically the loop is running multiple times while you are tapping that key...

to fix this, there are a number of ways... i had this exact problem when trying to get raw input.. i tried using timers, but for some reason that didn't work too well for me, so instead i check if the old key is == the new key.. pretty simple.

IE, do this:

if(key_pressed != old_key_pressed)
{
add this character to the string here
}

Eh?? You shouldn't be getting more than one unicode character per message loop unless you used SDL_EnableKeyRepeat(). I don't think it's turned on by default, the docs don't say. I'd assume no. Either way, you should only be checking for unicode in SDL_KEYDOWN events anyways since SDL_KEYUP events don't provide unicode symbols.

Also, check out this thread for more on SDL input

Drew Sikora
Executive Producer
GameDev.net

yes, only one per messsage loop... BUT, the key will still be down for longer then one message loop, so the key is registered multiple times per press, maybe like 5 - 15 times im guessing... is this wrong? if not, id like to know why its happening, as ive had the same problem, and my method fixed it.
FTA, my 2D futuristic action MMORPG
That shouldn't be happening. The SDL_KEYDOWN message is generated when a key goes from an upressed state to a pressed state. Once the key is pressed, the keydown event condition is no longer valid. So you should only receive the SDL_KEYDOWN message once per key press. As stated here, you should only receive more than one message per key press if you used SDL_EnableKeyRepeat()

The only thing I can think of that would generate more than one keydown msg per loop is if you weren't completely flushing out the event queue at the end of each frame, so the event would linger and appear to be generated every frame.

Drew Sikora
Executive Producer
GameDev.net

Already spoke with Lode about this on IRC. He wasn't checking the return value of his SDL_PollEvent call.
-bodisiw
Yeap that'll do it...

Drew Sikora
Executive Producer
GameDev.net

I also solved problem 2 quite neatly now, the function to check keys only returns the key if it isn't the same as the previous time you called the function. Only if it's a different one, or if you released the key and pressed the same one again after that, it'll return something. Now I should also add a timer to it so that when you hold down the key for a longer time, it'll start being repeated like in Windows :)

I solved problem 5 by using event.key.keysym.unicode.sym to check the numpad keys separately.
Quote:
3) I use SDL events not only for this unicode stuff, but also for mouse input, to check when you close the program, for NON-unicode key input (it's a game so you need to press arrow keys and stuff), and more. Appearantly, if I poll the event separately for each of those actions, it sometimes misses the action, most notably: if you want to close the window, but you press the close butotn with your mouse while it was just polling an unicode event for example, then the window does NOT close, and the correct polling misses it.
So, do I have to poll for events only ONCE, and use that one poll for everything, unicode input, mouse actions, closing the window, and so on?


yes, SDL_PollEvent() polls ALL events and then discards them from the event stack, so you must check for all types of events and handle them accordingly in an event loop like this

// sample function to capture all events that need to be handledvoid ProcessEvents(void){  SDL_Event event;  //SDL_PollEvent returns 0 when there are no more  //events on the stack.  while (SDL_PollEvent(&event))  {    switch (event.type){    case SDL_KEYDOWN: blabla; break;    case SDL_KEYUP: blabla; break;    case SDL_MOUSEBUTTONDOWN: blabla; break;    case SDL_QUIT: blabla; break;    }  }}


you could poll only one event per tick but then you may have a delay when processing them.

Quote:
Now I should also add a timer to it so that when you hold down the key for a longer time, it'll start being repeated like in Windows :)


SDL_EnableKeyRepeat(500, 200) worked well for me

from SDL Docs:
SDL_EnableKeyRepeat -- Set keyboard repeat rate.Synopsis#include "SDL.h"int SDL_EnableKeyRepeat(int delay, int interval);DescriptionEnables or disables the keyboard repeat rate. delay specifies how long the key must be pressed before it begins repeating, it then repeats at the speed specified by interval. Both delay and interval are expressed in milliseconds.Setting delay to 0 disables key repeating completely. Good default values are SDL_DEFAULT_REPEAT_DELAY and SDL_DEFAULT_REPEAT_INTERVAL.Return ValueReturns 0 on success and -1 on failure.
Now I get a cookie!

This topic is closed to new replies.

Advertisement