Sign in to follow this  

Good SDL string input

This topic is 3932 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey, Ive been trying to input into strings using SDL. At the moment im directly checking each letter in every loop. This is working, but i have come to a problem. To slow down presses i put in an SDL_Delay() after each key press. This improves the input. It keeps everythin nice and smooth. So when pressing "A" i dont end up with "AAAAAA" on the input. But even delaying after each press isnt working. Sometimes i have to wait before the next key. Or Sometimes it still goes too fast and i end up with sentances like "Hhheo Wrrrld". At first i tried an string input tutorial on LazyFoo. But the entire setup did not work well with my game code. I am not using a loop to poll events. But simply checking every key, every game loop. Is there an easy way to fix up this entire process? So my input is fast and responsive like windows? Thanks.

Share this post


Link to post
Share on other sites
Are you using SDL_PollEvent or SDL_GetKeyState to get your keyboard info? If you are using polling, this method really should work. Did you call it with SDL_DEFAULT_REPEAT_DELAY and SDL_DEFAULT_REPEAT_INTERVAL?

If you are using SDL_GetKeyState, I don't know if this function will help you or not.

Share this post


Link to post
Share on other sites
You're right, enabling key repeat does not affect the SDL_GetKeyStates information at all. I just tried it out.

You could either switch to using polling, or implement this behavior yourself. If you do it yourself, I'd use a timer to only check the keys every X milliseconds rather than using SDL_Delay, which as you found out, is too unpredictable for this.

Here is a quick demo of this:

// keys.cpp

#include <SDL/SDL.h>
#include <iostream>

int main( int argc, char** argv )
{
SDL_Init( SDL_INIT_VIDEO );
SDL_Surface* screen = SDL_SetVideoMode( 800, 600, 0, SDL_SWSURFACE );
Uint8 *keys = SDL_GetKeyState( NULL );

unsigned int timer = 0;
unsigned int last_time = 0;

while( true )
{
SDL_PumpEvents( );

timer += SDL_GetTicks( ) - last_time;
last_time = SDL_GetTicks( );

if( timer > 500 ) // half a second
{
timer = 0;

if( keys[SDLK_LEFT] )
std::cout << "LEFT" << std::endl;

else if( keys[SDLK_ESCAPE] )
break;
}

SDL_FillRect( screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0) );


SDL_Flip( screen );
}

SDL_Quit( );
return 0;
}



HTH

Share this post


Link to post
Share on other sites
Hmm. Trying that, im getting the same problem as before. As much as i tinker, the input is still irritatingly bad.

I was thinking, possibly if i could only block the same key being pressed again for 100ms? But im not sure on how to implement this?

Share this post


Link to post
Share on other sites
If you just block the key from being pressed for 100ms, then slow typers (who hold a key down longer than 100 ms) will have problems.

You can use both polling and SDL_GetKeyStates() together. Use polling to test for things like typing text and pressing 'event' buttons (escape, menu button, fire missiles button, etc.) and use SDL_GetKeyStates() to test for things like smooth motion (arrow keys, other keys that are either up or down from the game's perspective).

SDL makes both types of information available to you; you might as well use whichever is easier for a given part of your program.

Share this post


Link to post
Share on other sites
Just wanted to reinforce that you should use polling rather than key state querying for text input. The behavior that you're trying to emulate you will then get 'for free' (assuming appropriate key repeat and delay settings, of course).

Share this post


Link to post
Share on other sites
Ya I'd have to agree with jyk, just have a polling loop like in every SDL tutorial , and have any key up event inside the ASCII range your looking for casted to a char and send to your buffer.


SDL_Event keyevent; //The SDL event that we will poll to get events.
String strInputBuffer = ""; // This is where you will store typed keys

while (SDL_PollEvent(&keyevent)) //Poll our SDL key event for any keystrokes.
{
if( keyevent.type == SDL_KEYUP ) // Check if this key is being released
// Check if the key is in the upper or lowwer case ASCII ranges
if( keyevent.key.keysym.sym >= 65 && keyevent.key.keysym.sym <= 90 ||
keyevent.key.keysym.sym >= 97 && keyevent.key.keysym.sym <= 122 )
/** This is either an upper or lowwer case letter,
* add it to the buffer, This check can obviously
* be easily modified to allow for numbers and more.
* But it is important to prevent the ASCII values
* of control keys or others from being nonsensically
* added to your buffer.
*/

strInputBuffer += reinterpret_cast<char>( keyevent.key.keysym.sym );
}








Guess it's important to note that the SDL Keysym enum is mapped to UNICODE, which in turn has it's lower range of values mapped to ASCII.

*edit* Um, so I'm 100% sure that the SDL Keysym enum has it's lowwer range mapped to ASCII, but I'm not 100% sure of the upper range being mapped to UNICODE. I was looking over the source and they say something about following in the foot steps of X11 with virtual keys for international key boards. So it would be my guess it does not follow UNICODE. Does anyone know for sure?

Hope that helps.

Share this post


Link to post
Share on other sites
I tried your method Wave but it wouldnt compile.

So i went on and tried somthing simple like this




while (SDL_PollEvent(&event))
{
if( event.type == SDL_KEYDOWN )

{
switch(event.key.keysym.sym){

case SDLK_a:
str = str + 'a';
break;

}

}

}



And it maybe will catch one or two out of a hundread keystrokes? Be aware this has just been dropped straight into my Update loop.

Share this post


Link to post
Share on other sites
It should be catching every single keystroke. The keyboard generates events every time a key is pressed or released. The operating system sends these events to the program, and SDL generates the corresponding event which is then placed in the event queue. The only way to not detect a keystroke is if the keyboard doesn't detect it or there is a glitch in the software somewhere.

Share this post


Link to post
Share on other sites

This topic is 3932 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this