Keyboards, Joysticks and Game Controllers : ideas for best practices!

Hi everyone,

This is my first post here so hopefully it’s not too spammy! I’m getting to grips with SDL now and trying to write a simple 2d game framework for practice (Pong et al.) before moving onto something more ambitious! I’m having a few issues with the Joystick/Game Controller handling; it’s becoming clearer but hopefully someone with experience can answer a few queries I have and speed things up! And for completeness, I’m using SDL 2.0.6 with Ubuntu 16 LTS.

  1. Events vs polling : I tried polling at first (looking directly at the keyboard, mouse states etc…) but now trying events. Apart from the extra work in handling everything manually with events, are there any advantages/disadvantages? One reason I switched is I thought I would bite the bullet and go for a fully event approach (also in my own framework internally) but not sure if that’s best for the SDL stuff. Any feedback from people with experience with both would be appreciated.

  2. Initialise game controllers first or joysticks? It seems you can open the controller first and then get the joystick handle or vice versa. I’ve noticed with the events that the game controller open event seems to come before the joystick opening event so I open the game controller first, but not sure if this is the best way or not.

  3. Accelerometers. With Android, I’m using the SDL hint to use the accelerometer as a joystick. However, when I check with my version of Android, there are usually THREE joysticks immediately attached (not sure what the other two are). To find the accelerometer, I simply loop through them and find the one with 3 axes! This works in my case and probably many cases but seems a bit hacky and not so robust. Is there any better/more robust way of identifying the accelerometer??

  4. Game controller mapping. Okay, this is not a strictly SDL-only thing, but thought I’d ask it here also since it’s related. I’ve got no experience with these mapping strings. Presumably you have to parse them in some way and then set your button mappings in your own code. Any tips, or perhaps some online reference I can look at?

Thanks in advance for your help :slight_smile:

Hi @sergamer, and welcome! Cool to hear you’re writing a simple game engine — it’s a great way to learn about the lib and concepts in general. I’ve been hacking on mine for a few years now, aptly named Simple 2D, and have learned a ton.

Regarding your points above:

  1. I wasn’t aware there was an events-based approach supported by SDL. I’ve only used polling (example) given you aready have a loop in a game anyways. I do find that events are a bit nicer to expose to apps which use the engine. Here’s my callback approach. All just style and preference I suppose.

  2. I wrote a little “detect controllers” helper, which might be of use. I don’t have this wired in as an event yet, just calling it manually at window init.

  3. You’re ahead of me here, so hopefully I can learn something with you. I actually don’t have any Android support in my engine, so that’s something I want to figure out generally, and best practices, etc.

  4. This is also something I’d like to figure out with you. Just Googling “sdl controller mapping” comes up with a lot of good stuff, so might just have to dig around.

Thanks,
Tom

1 Like
  1. the normal way is to do a SDL_Event ev; while(SDL_PollEvent(&ev) { /*
    … handle event ev */ } loop each frame
  2. You usually iterate the available joysticks and if one is a
    gamecontroller, you can open it as one. see
    https://wiki.libsdl.org/SDL_GameControllerOpen
  3. no idea
  4. you can just feed a mapping string into
    https://wiki.libsdl.org/SDL_GameControllerAddMapping
    or load a whole text file full of mappings with
    https://wiki.libsdl.org/SDL_GameControllerAddMappingsFromFile
    And there is even a way to set such a mapping with a environment
    variable: https://wiki.libsdl.org/SDL_HINT_GAMECONTROLLERCONFIG (the
    corresponding name vor the environment variable is SDL_GAMECONTROLLERCONFIG)
    Afterwards the device should be recognized as a controller when
    iterating the available joysticks
1 Like

Hi guys,

Thanks for the replies. A few comments back :

  1. @Daniel_Gibson . Yeah, I do the event loops that way. What I meant was, what are the advantages of doing them that way compared to polling the keyboard, joystick states. One thing I forgot to mention in my original post was that I read in several places that controls already plugged in at start-up have to be looped over and connected manually whereas any subsequent controllers have events sent. So this is one thing, but I guess there must be other pros/cons? Anyway, I’ll probably stick with the event-based approach now anyway. @blacktm : Yes, definitely some style-preference there. Like I said before, since I’m using events elsewhere I’ll try and be consistent everywhere.

  2. @blacktm : I have a similar block of code for mine so it’s good to see they are similar (so must be correct, right? :wink: ).

  3. I tried a different Android device and this time only detected one joystick (i.e. the accelerometer), weird! Anyway, it’s a hack but it’s a hack that works (for now) so I’ll just stick with it and actually make a game finally!

  4. @Daniel_Gibson : The thing is, I have no idea what this all really means :slight_smile: (apart from guessing of course). What would be good is if there’s some online example of say connecting a controller, adding some mapping and then showing how to detect button presses from say the right shoulder button. Atm, I’m a bit stuck on how to do all of that.

Thanks again

Regarding #4, reading some blogs, I guess it’s as simple as watching for events SDL_ControllerAxisEvent and SDL_ControllerButtonEvent (I’ve been using joy events) and things get mapped to what’s in SDL_gamecontrollerdb.h automagically…? Will have to give that a try.

Regarding #3.

I’ve worked a lot with the Android build and controllers. You will see a lot of joystick devices that aren’t joysticks. Keyboards and air-mice are being picked up as game controllers due to a bug in SDL. I thought this got fixed, but clearly not. Look in SDLActivity. Keyboards (even software keyboards that are built with mobiles / tablets) usually have some kind of DPAD, so SDL mistakes these as joysticks, which also disables the DPAD (arrow keys, usually) from producing keyboard events, so I found remote control directions weren’t working in my game because they were going to joystick events. I put a condition in there that filters out the DPAD stuff, so you just get true game controllers.

Accelerometer as a joystick is the best way, then do a strstr() lookup of “accelerom” from SDL_JoystickNameForIndex(). Still a bit hacky, but better than looking for 3 axis.

1 Like

@blacktm : Thanks for the link. I’ll try and get something up and running to read the game controllers in the next day or two, fingers crossed

@AntTheAlchemist : Thanks, that’s very useful to know. I will definitely use that string check instead of the 3-axes check. Actually thinking about it, I was using SDL 2.0.4 with my older Android phone and updated to the latest 2.0.6 version when I tried with my newer phone, so could very well be that bug has been fixed. I’ll see if I can reproduce that with my latest code version (although I think the 2.0.6 version is incompatible with my older phone since the Android version is too old).

BlockquoteActually thinking about it, I was using SDL 2.0.4 with my older Android phone and updated to the latest 2.0.6 version when I tried with my newer phone, so could very well be that bug has been fixed

I haven’t tried 2.0.6 on Android yet. Hopefully that’s fixed now. Actually, I haven’t been able to build anything SDL related on Android since Google stopped supporting ANT. Did you have any problems setting up the Android build? I might come crawling to you for help :slight_smile:

Does 2.0.6 raise the minimum API level? What type of dessert is your old phone?

More about how I handle controllers: I have one global event handler switch to handle all types of events and pass them on to various class handlers (Joystick class / Mouse class, etc). So then my game can just use these classes to poll input. I open each game controller as a Controller if it is one, then get the Joystick handle from that, or just open as a Joystick. I use controller events to set accurate XBOX360 type information, but if there is no mapping, then I assume joystick axis 0 is x, and joystick axis 1 is y. I assume button 0 is A, button 1 is B, etc. This woks 90% of the time. I purchased about 10 different game controllers from eBay (mostly from China) to test them. Only one type gives me odd axis information which I can do nothing with (but strangely, Windows calibration works ok with these axis - I’ll post about this later). Only one controller has SDL mapping (the fake XBOX controller).

Hope my experiences have helped. If I can help more, just ask.

@AntTheAlchemist : I think it was Android 4.4 (definitely one of the 4s) but my newest one is Android 6. Yes, there are at the very least some includes in the latest versions of SDL (both 2.0.5 and 2.0.6 I believe) only found in newer Android versions so it didn’t compile with the older ones.

Actually, I’m still using an older version of the SDK, one with Ant, i.e. using ndk-build + ant to compile things on the command line. I guess the latest ones have got rid of it already and I’d have the same issues as you if I used the latest ones. So I probably wouldn’t be much help sorry. And I have to say, I’m not looking forward to the day when I’m forced to use the latest versions and have to re-learn/design my whole perfectly working (for now) build procedure :-/

About the controller input, this sounds like how I’m doing things myself so good to know I’m on the right track. I’ve got about two game controllers, one cheap generic one and one a PS3 one. So I’ll try those first of all and if I can get two different types working, then hopefully I’m sorted.

Thanks again for your help.