Jump to content
  • Advertisement

Recommended Posts

Hey there!

Two weeks ago I started working on a small, open-source project, similar to GLFW. 

I am currently stuck at lining out the proper interface for keyboards. As of now, I am having a static method `keyboard::is_pressed` and a huge enumeration with *some* keys, 
I found on my keyboard. As the name already implies, `keyboard::is_pressed` asynchronously reads the keyboard state and returns true, if the physical key corresponding to the 'virtual key' - passed as argument - is pressed.

This approach, however, feels 'clumsy' or maybe even 'naive' and I feel like there could be a better way to solve this problem, which I am aware of.
So, therefore I am asking here: 
Are there any patterns I am missing out on? Do you have any suggestions on how to solve this problem elegantly?

Regards,
Julian

Share this post


Link to post
Share on other sites
Advertisement
2 hours ago, Julian Kirsch said:

Do you have any suggestions on how to solve this problem elegantly?

Take a look at the GLFW source code while sashaying. 😀

Share this post


Link to post
Share on other sites

Well, depending on your goal, your solution is fine.

SFML uses the same kind of API: https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Keyboard.php

But SDL2 has a much more complex keyboard API: https://wiki.libsdl.org/CategoryKeyboard

 

I have found some issues with the "simple" SFML and your proposed way. Which is most likely also why the SDL2 API is much more complex. In general, there are 3 different types of keyboard input:

  1. Pressing a specific physical key on the keyboard for an action (Use WASD keys for movement, independed of keyboard layout)
  2. Pressing a specific named key on the keyboard for an action (Press "A" to continue, where A is located depends on keyboard layout config)
  3. Typing text, coverting key presses into specific text entry actions. Pressing shift gives nothing, while shift+A is an upper case A. Generally this is more event based.

 

For my home grown game engine, I've build an abstraction called "KeyBinding", which solves a few different things as well, like:

  • Multiple keys bound to the same action
  • Checking if the key was pressed/released this frame/update cycle
  • Assigning joysticks axis to keybinding as well
  • Saving/loading keybindings to a file

https://github.com/daid/SeriousProton2/blob/master/include/sp2/io/keybinding.h

So consider what level of abstraction you are providing, and what your end goal is.

 

Also consider whether you want keys to be pressed if your application has focus or not. Big surprised if you alt-tab to a browser and the game keeps reading your input.

Share this post


Link to post
Share on other sites

My code uses the HID interface and platform dependent APIs to get the input (not just Keyboard but also Mouse and GamePad). On Windows (and I think Linux too) the HID driver is populating messages to input receivers (a Window). This way what I did was to attach my input system to the main window of my application and have messages be processed as they enter.

This "event driven" input has the advantage to not query the hardware all the time but instead store updates in some kind of input manager. I also not use specific keys or key events directly like the 'A' button but instead generate a 16 bit UID for every key as it provides a state change. The UID is calculated (shifted) from the bist of the HID result like the Usage ID and the key code/mouse button or button/axis ID

Share this post


Link to post
Share on other sites

Oh, and I checked your code, you seem to use "GetAsyncKeyState" for windows at least, I guess something along the same lines in linux. I've had players manage to press&release a key between 2 frame calls with that kind of setup. So I would recommend against it for things like quick arcade like games. As people get pretty annoyed when they press the jump key and nothing happens.

Share this post


Link to post
Share on other sites

@Daid Thanks for your input 🙂
So far, I am planning to keep the level of abstraction low. However, you're 'keybinding' implementation inspired me and will, perhaps, be implemented as a utility on top of the 'low-level' primitives of my library.

Also, thanks for your link to the SDL2 docs. I will probably orient myself to it, when developing the API.

@Shaarigan Before I wrote this post, I was planning to use HID-Input/RAWINPUT but I thought requesting it every time would be better. Is the overhead really this intrusive? 
Also, do you have, by any chance, an idea on how to implement this for linux without requiring sudo? As much as I have gathered so far, I require root privileges to read the raw input data from the fd's.

@fleabay Thanks for the tip! I found its interface to be somewhat similar to SDL's. 

 

Share this post


Link to post
Share on other sites

I know from someone at a AAA studio that you'll need some kernel functions (userspace) to aquire HID on Linux but he dosen't mentioned anything from root-privileges. I'm not at the point where we are working on the Linux port so I'm a bit out of experience here but there is a reference Lib on GitHub you might want to take a look at.

Generally for gameplay you want as less API calls as possible, so polling the state of an input key every few ms and possibly multiple times per key isn't very performance improving. You 'ld needsome type of caching the poll but this will become very complicated in a multithreaded environment. Because in async processing you'll need to know when a frame ends and the next frame starts to invalidate the state for that certain key.

Going into an event based system, you update the state just when an OS message arrives and anything else is handled by the comes first/serves first principle

Share this post


Link to post
Share on other sites

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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!