User Input methods and Key Chords

How can I handle Keyboard KeyChords as Alt-ENTER, CTLR-F or SHIFT-T?

Also there is three ways to handle input one is SDL_PollEvent() the other is SDL_GetKeyboardState() and the third one is SDL_TextInput(), I know that ask about the “best one” or the “right one” is the wrong question, instead I ask:

What are the pros and cons of each of these methods? Where each of them is better suited? To develop a game which one is used and where?

Update: I was able to handle KeyChords uinsg the keyboard states as:

const u8 *ks = SDL_GetKeyboardState(NULL);
if(ks[SDL_SCANCODE_LALT] && ks[SDL_SCANCODE_RETURN]) do_alt_enter_pressed_action();

But I still would love to hear from the veterans…

PS: Trivia question what is a XOR Key in numpad? Keypad XOR " (the XOR key (numeric keypad))?

1 Like

I think unless you really know better (you don’t) or you’re porting an existing game which already uses code that fits better to SDL_GetKeyboardState() model, you should use SDL_PollEvent() (there’s no EventPool).
Even when using SDL_GetKeyboardState() and SDL_GetMouseState() etc, you still need to call SDL_PollEvent() so you get SDL_QUIT and window events etc that you’d otherwise miss - and to make sure SDL processes new events internally (though SDL_PumpEvents() can also be called to make sure this processing happens - in fact, SDL_PollEvent() calls that implicitly when running out of events).

Anyway, there are more interesting keyboard-event related things to consider:

  • For textinput always use SDL_TextInputEvent (event.type == SDL_TEXTINPUT). One logical character can be created by multiple key presses (e.g. on keyboardlayouts with “dead keys” ´ + e produces “é”), so the SDL_KeyboardEvents are useless for this.
    (Exception: for handling the backspace and delete keys for deleting characters, or cursor keys to move the text cursor etc you still need SDL_KeyboardEvent - but for the actual text, use SDL_TextInputEvent)
  • Familiarize yourself with what SDL_Keysym (from event.key.keysym in SDL_KEYDOWN and SDL_KEYUP events) contains.
    • keysym.mod will tell you which modifier keys are currently pressed, which is relevant for your Alt-Enter, Shift-T or Ctrl-F examples.
      if( event.key.keysym.sym == SDLK_f && (event.key.keysym.mod & KMOD_CTRL) != 0 ) printf("CTRL-f is pressed!\n");
  • Be aware of the difference between keycodes (SDL_Keycode) and scancodes (SDL_Scancode).
    • Keycodes (event.key.keysym.sym) refer to the logical keys: the key labeled with “E” will produce SDLK_e etc. However, on non-English-keyboards there are lots of keys that don’t have a corresponding SDLK_* constant, like the Ä key on German keyboards - generally this is the case for characters that don’t exist in ASCII. Those still get a keycode, which corresponds to the unicode value of the lowercase character of the key (for the Ä key I get keycode 228, which is the unicode value of ‘ä’).
    • Scancodes (event.key.keysym.scancode) refer to the physical location of the key on US-QWERTY keyboards (and are the same values as used in the USB HID standard). So they’re independent of the keyboard layout - the key next to Tab is always SDL_SCANCODE_Q, even if you have a french AZERTY keyboard where that key is labelled ‘A’ (so its keycode is SDLK_a).
    • You can translate between scancodes and keycodes with keycode = SDL_GetKeyFromScancode(scancode) and scancode = SDL_GetScancodeFromKey(keycode) - of course what these return depends on your current keyboard layout.

So what you’re going to use depends on what you want to do.
For games it’s often useful to internally use scancodes, so your key bindings (which key will make you go forwards etc) always refer to the same keys - that way WASD becomes ZQSD on AZERTY layouts - WASD is not useful on that layout because W and A are a totally different positions.
Of course, you need to convert those scancodes to keycodes to display them to the user - they don’t care if you use scancodes internally, they need to know what that key is called on their keyboard.
const char* keyname = SDL_GetKeyName( SDL_GetKeyFromScancode(scancode) ); helps with that - keyname will be the name of the key as printed on the users keyboard for the given scancode.
On the other hand, sometimes keys have a meaning that’s more related to their name than to their position on the keyboard (“Press [I] to open the inventory!”) - in these cases keycodes are more helpful - and mixing keycodes and scancodes can cause problems, imagine SDLK_i corresponds to a scancode that you’re using for something else - it would suck if e.g. walking to the right would open the inventory…

PS: Reading your topics I wonder if the existing tutorials (or at least the ones you read) and the wiki are not very helpful to teach the key SDL concepts to beginners, or if you just didn’t read many SDL tutorials and the documentation wiki. As someone who started using SDL with SDL1.2 and IIRC mostly learned it by reading existing code that uses it, I honestly can hardly tell how good or bad the commonly known SDL2 tutorials are for beginners, or how useful the SDL wiki is if you don’t already have a rough idea what you’re looking for and how things work.

1 Like

It was a mistype. Late of night. Sorry.

Yes. There are other events besides Keyboard and Mouse.

Didn’t know that. Nice to know.

Yes. I realized as soon you have explained about Keycodes and Scancodes above.

That a funny problem to face.

There are some layers here. But let me start from somewhere…

I have read many tutorial, have ran through LazyFoo’s ( http://lazyfoo.net/tutorials/SDL/index.php ) , Parallel Realities (https://www.parallelrealities.co.uk/tutorials/) , TwinkleBearDev (https://www.willusher.io/pages/sdl2/). Also have read Saun Mitchell’s SDL Game Development, and part of Pazera’s Focus on SDL. Often I use WIki SDL pages for function references and guide lines. Those are very useful and for sure help me a lot.

Even reading all that stuff there are other problems.

  1. Its hard to remember everything: Nobody is able to store all that information from a single read, real knowledge comes from practice and repeating from errors.

  2. Secret tools of trade: No tutorial/books explain the tools of trade, maybe for some reasons: a. they are too complicated to newcomers, b. will be explained in a near future (but the future didn’t come), c. laziness; or d. forbidden by game developers secret society. Just for sake of example, besides some tutorials (not all of them) explain about KeyCodes and Scancodes, none of them bring the attention about the issue of mapping in keyboards in different languages. I know that once you start to think about the problem it’s natural to understand, but seems that in game development (more than any other areas) there is a caveat monster hiding in every corner.

  3. Simplified approach: Most tutorials take subjects in a very simplified approach and very segmented way. Each concept is explained isolated and when coupled together seems very loose and not robust. Most of time is said: That is not how things are really done, but I explain using this method because is simple. Everything else is expected to reader to learn by itself.

  4. Learn from veterans: Probably most of people here in this group work in a game company, and each one has a different level of expertise. It’s simpler to learn from someone if you have examples to follow and guidance, unfortunately I do not have those. It would be lovely If I could be able to work as a junior in a game dev company to learn how things were done, but that isn’t my reality. My background is the university, I have a degree in Applied Math, my two areas of expertise are numerical simulations of partial differential equations and statistical learning (aka AI). Both of them are used in game development but in a VERY different approach. In game engines, they often use a very simplistic integrator (euler, verlet), everything else isn’t feasible since in games we are more worried about speed than precision, I really can’t see Finite Element Methods, being used to model anything in game industry. In other hand. deeply what I want to do is code games (and maybe apply some of my knowledge on them), there is a huge gap to fill from what I learn in academia and how to code a video game. Not to tell about the prejudice that exist in academia when talking about looking seriously to game development (at least here in Brazil).

That being said, I’m a sum of all those components, but I can’t say anything other than thank you (and everyone else) for all answers.

1 Like

There are some layers here. But let me start from somewhere…

Thanks, this was quite insightful :slight_smile:

I don’t think there’s secret tools of the trade - game companies tend to be quite open about their technical inventions, for example see all the presentations and articles on new rendering approaches, for example.
And of course what SDL does is relatively basic, especially from a using-SDL point of view (the internals with workarounds for weird platform quirks/bugs etc can be more advanced of course, SDL contains lots of knowledge/experience!).

Of course this doesn’t mean that how to best use SDL is obvious, or that everyone knows it…

You’re right that tutorials are usually simplified - and they have to be: Getting into all details would make even a simple tutorial that opens a window, displays some image and closes it again if a button is pressed so long that no one would read it.
Imagine having all the information about keyboard input that I posted above in such a tutorial, and maybe similarly detailed explanations for window creation/handling, rendering, …

I wonder if there’s a way to teach (or document) the key concepts of SDL2 that at the same time is short enough not to scare away beginners, but still allows them to get in-depth information if they want or need it - writing good tutorials (that ideally are useful for a different kinds of learners) definitely is hard!

Another problem I frequently see with beginners asking SDL questions is that their actual problem is not SDL, but not really knowing C or C++ (whichever they use) or even programming at all, so they’re basically trying to learn SDL and C(++) at the same time which I imagine is very hard for tutorials to accomodate for - you don’t wanna bore readers who already know how to program with very basic things that have nothing to do with SDL…
(Note that this is about issues I observed SDL beginners are having in general, not (just) you in particular)

BTW, I also agree that learning from veterans is probably the easiest way, but I’m not sure if this is really that common - I think usually people who start working (as a programmer) at game companies already have some basic knowledge of programming games in general, and I guess it’s rare that one learns SDL from seniors at the job.

Warning: Long text.

TL;DR: I think we need to have tutorials to fill the gap between basic functions and real use cases.

I think that my feel is like be drowned in too much information, there are many papers indeed, presentations, talks, GDC math/physical/rendering sessions. Humbly I think there is a gap here to be filled to enhance the transition from a non game developer to a game developer.

Or that someone say how to do it. It’s very different to say “This function does this” to: “If want to implement this feature use this function”.

The first approach puts on reader the weight to connect the ideas and uses, some of them are not clear when the reader is reading about that function.

A good and recent example was the International keyboard issue that we discussed previously. I had already read about both ways (Scancodes and Keycodes), but in time I was reading I didn’t saw the whole picture, maybe in a future I would face exactly that same problem and I would remember (or not) of the function.

The second approach is better (IMHO), since we start with a practical problem and a usage, in both methods you learn about the codes, but just on second one you get on a real use case, and real use cases are more suitable for learning and memory fixing.

I’m not saying that tutorials need to be complex, I think they are very good and help a lot newcomers. But as I said before there is a “documentation” gap between tutorials and real use, is often left (implicitly) to the reader.

It’s far different to

  1. lets create a character and move it around with gamepad/mouse.
  2. Lets create a way to handle game entities being controlled by configurable user input methods.

The complexity of code gets far bigger in the second option. In fact right now I’m trying to do exactly this. How should I map a user input with a in game event. How can I reconfigure a user input for a different in game event. How can I handle different user input methods, should I treat them differently? Should I add a layer?

For example I could not find any “tutorial” explaining how to do it (SDL or not).

IMHO There are levels. Many people have already written tutorial about basic drawings, primitives, basic game loop, drawing a few sprites. But I could not find SDL tutorials to fill gaps after that. Ok, we can handle 1, 2, 10 sprites, but how to manage association between a character and it’s animations? How to connect inputs to characters and animations, how to transition between states? Of course this is a far more complex thing than teach about topics isolated 1. Drawing sprites, 2. drawing animated sprites, 3. handling game input. 4. a simple Finite State Machine. The total complexity is larger than the sum of complexity of each parts.

Sure it is.

Indeed. Although I personally do not feel I fit the “non-programmer” profile, besides I’m not a C (not C++…) wizard, I can code using pointers very well (not by trial and error as many do), I can write my own structs, dynamic loading, pointers to functions, have even written my own C Poor Man’s Object Oriented approach using Vtables. I’m not good in C as I would like, I don’t know ASM and because of that I have problems to optimize code and debug very well (I will fix this in near future). I don’t know enough of C internals and implementations details to be able to write a complex multi architecture and multi plataform software (and I would like very much to learn that). Have completed with success (and a good grade), algorithms and data structure courses in graduation (implemented myself lists (all kinds), queues, trees, hash maps, search algorithms, path algorithms, computational geometry algorithms), also worked with numerical computation (differential and integral multi dimensional equations).

The problem is most of these issues are handled in a separately, I wrote an algorithms to find a path there, an search heuristic in another code, code to verify spatial positioning, but never together, never really caring about performance.

And when its come to game development is all about performance. I had started to write a entity lookup system using an ordered array, where the order is based in the object UUID that is a string. The struct was like

struct entity {
     char uuid[37];
     // .. other entity stuff
};

My available objects were stored in a array (for memory speed).

struct entity active_entities[MAX_NUMBER];

Adding new elements to array of course, would take some time, since I need to order the array. Because of that I created a delayed sorting, with that I’m able to just append new entities then sort them.

Of course to find a entity handle (its index position in array) I need to somehow find it using a search algorithms (binary search is a good one here since we have a ordered list based on UUID strings.

I was happy with that, then, watching some GDC video someone said: If you use string comparison you should be shot in head.

Then I got thinking, what to use? A hash map? But isn’t memory contiguous hence not cache friendly.

The problem is, I always get myself in that kind of dilemma, and never move forward.

(and here I’m not even discussing about Object orientation vs Data Orientation designs, that I’m far more inclined to the second one to avoid cache misses).

I have worked in software development (in scientific computation), there is no need to be a “coach” attitude, but in a working environment you often get in discussions like, how to approach to a problem, their experiences and methods, what worked best for each case.

In industry (not gaming industry) I often saw that junior employees has a bare minimum knowledge, and by minimum I say really minimum.

Finishing off, it’s hard to be a wannabe indie developer in game industry, there is a lot of things to learn, Engine development, Rendering Pipelines, Audio Processing, Physical Collision techniques, Code optimization, Usability and game feel, Game design. It’s being a hell of a trip, but I’m really enjoying.

Hope I can learn more from all of you, and sorry for my questions that often can seems like kind stupid sometimes.

(Due to lack of time I might answer the tutorial-specific points later)

I don’t know enough of C internals and implementations details to be able to write a complex multi architecture and multi plataform software (and I would like very much to learn that)

For that you don’t need to know C internals but (usually boring) platform-specific APIs - but that’s what SDL and other crossplatform libs are for ;)
Also, if you do this as part of a team you don’t need to take care of all that, esp. as a junior.

Adding new elements to array of course, would take some time, since I need to order the array.

Would it? You “just” need to find the right position to insert each new element (maybe with binary search?) and then memmove() all the following elements one position to the right so you can insert the new one there. Shouldn’t be super expensive (memmove() is fast!), unless maybe you create lots (hundreds? thousands? no idea even, you’d have to try) of new entities every frame…
Try it out, maybe measure how long it actually takes, you’ll be surprised how fast adding a few elements to a sorted array actually is.

I was happy with that, then, watching some GDC video someone said: If you use string comparison you should be shot in head .

Game programmers tend to have opinions and like to voice them strongly. That doesn’t mean they’re always right :-)
I’d say string comparisons aren’t that expensive, especially if the strings have a limited length (and you compare them case-sensitively, i.e. it’s just a byte-wise comparison without additional processing).
OTOH maybe an uint64 (or even int32) would be enough for your ID? They’re even cheaper to compare of course, and it would decrease your entity object size which makes your array of entities more cache-friendly…

But don’t let that kind of shit discourage you: Just implement your thing the way you want and chances are good it runs fast enough even on older hardware - and if not you can still optimize it (and profile it to find out what’s really slowing it down, which can often be quite surprising - also debugging and profiling are very valuable skills!).
Those gamedev veterans bitching about every inefficiency often need to make the latest AAA games run on limited console hardware, with as many details as possible - that’s very different from the kind of project you do as a beginner.

I totally get that you want to get it perfect on first try (this has held me back often enough!), but in reality the best way to learn is to just do something and then improve it if necessary - or if it doesn’t seem fixable, identify the mistakes and try again.
Especially for small projects (and you don’t wanna create a super complex game as your first project) this is actually faster than endless planning and rejecting ideas you haven’t even tried ;)

Finishing off, it’s hard to be a wannabe indie developer in game industry, there is a lot of things to learn, Engine development, Rendering Pipelines, Audio Processing, Physical Collision techniques, Code optimization, Usability and game feel, Game design. It’s being a hell of a trip, but I’m really enjoying.

You don’t have to know all these things, in fact very few people do!
It’s totally ok to specialize in something (as you can see in many job postings at gamedev studios).
For example, many people are gameplay programmers and they don’t need to know all that much about Engine development, Rendering Pipelines, Audio Processing, Physical Collision techniques, and neither about usability or game design - the former should be handled by engine developers (or by using an existing engine), the latter should be handled by (game) designers who tell you what they expect your code to do (and you figure out how to best do that).
Or they’re rendering engineers, in which case they probably don’t have to know much about collision physics or audio or AI or gamedesign or …
So when I wrote about “basic knowledge of programming games” I meant that you’re should be familiar with whatever sub-field a job posting is about, because I think that game studios usually expect more than “bare minimum knowledge”. But that doesn’t mean you need to be familiar with everything, and you certainly don’t need to be an expert at everything, and of course you’ll learn more on the job :)

Regarding that “gap” between (usually simplistic) tutorials and API documentation:
Maybe articles could bridge that gap?
For example, my first answer above (maybe expanded and refined a bit) could be an “Keyboard input handling in SDL2” article, and it could be linked in tutorials (“for more information on keyboard input see this article: …”) and maybe also in the Wiki at https://wiki.libsdl.org/CategoryKeyboard (and https://wiki.libsdl.org/Articles).

In contrast to tutorials such articles don’t have to bother to provide “full” code examples (that have to do unrelated things like creating a window to work at all), so they might be more inviting to someone who already read tutorials and doesn’t want to read all the boring parts again - and at the same time they can provide a more holistic view (though still about a specific topic or subsystem) than API documentation usually provides.

I think articles pinpointing particular areas and giving a deeper insight about how things are normally done is a very good approach. Maybe, after all my time learning user inputs I can write something worthy too.

Agreed. Not complete source code but something that can be reasoned about and materially discussed.

But it’s always a good test case if you have some code to compile and show things working. Just for sake of example I’m learning a lot reading SDL/test subdir.