Making a Game Part 6 – Reconfigurable Hotkeys

Hello and welcome to this second to last blog post on the makings of this game.

So, this week I had some trouble deciding on which artifact to post about as I have been mostly fixing some issues and various bugs in the game, such as having no ammunition if you restart the game after winning and adding a small high-score system to motivate the player not to kill the guards as you now get a ninja-reward if you manage to complete the game undetected and without killing anyone.
I also added doors, but that did not take very long and just uses the same basic principles as the walls that Sebastian in my team had previously made, in that it collides with the player and casts a shadow.

And so I decided to write about the hardest thing I tried implementing, which is to let the player decide which key binds to use in the game.
First I started trying to figure out what the best way to tackle this was, as I didn’t want to have to hard-code everything button for button but also needed a visual representation of every button (A is the number 0 in SFML, B is 1 and so on) and there is no way to convert the number into that letter to show on screen (technically the sf::Event::TextEntered can do this, but it doesn’t handle the ctrl,alt,shift,tab etc. buttons so that would not solve the problem), and seeing as how a player probably wouldn’t understand what button  27 or 19 means I needed a way to convert the keys into text.
The solution: making a text file that listed every handled button in SFML that is then read by the program and put into an std::map<int, string> where the int is the value of the button and the string is the button it represents (0, A).

Now I needed a defined set of actions that I can bind these values to, so after making an InputManager with an Enum containing every handled action i made another map that holds these actions along with a string containing the int returned by the sf::event::keypressed and the string that is the name of the actual button (so the string would look like “11 K” or “37 LCtrl”), so after making about 14 different methods to convert everything to anything I could finally start trying to make the actual rebinding possible.

This is when I created another state in the game called rebinds that you can reach through the options-state and added a bunch of buttons (a new class called RebindButton) with active/inactive states and labels and all that stuff, the cool part was that it accessed the actions in the InputManager in order so the first button would get the label of the first action along with its bind for the current-bind-label and then made one button for each action.

That made what you saw in the last post possible:


So now the button-values that the sf::event::keypressed returns is converted into a string that tells the program that 5 means E, now we just have to make it change the string and then to save it into a file to later be able to use the bind in the game.

What I did for this was do a collisioncheck when you click the left mousebutton to see which of the rebindbuttons are being pressed and then using a method called WaitForInput (seen below) that waits until a button has been pressed and then sends the keyvalue returned by the event into the inputmanager where it is then set as the current bind for the action that was clicked, while also returning a new label for the RebindButton to show.
I later added a fail-safe to make sure that the player doesn’t bind any buttons to more than one action, and also making Escape cancel the rebinding.


The last thing I added was to actually use the bind ingame, this was done by converting the keybind through the std::map with the actions and returning the key currently set for it and then static casting it to to a sf::keyboard::key and compare it to what the sf::event::keypressed returned.
And after some final touches to make it look a bit more fancy (with centered text and no underscores in the names) it now looks like this:

The Set Defaults was added later on and is basically just hardcoded binds that are set when you click the button.

That is all for this time, I hope you enjoyed reading and I’ll see you in a week for the final part!

One comment on “Making a Game Part 6 – Reconfigurable Hotkeys

  1. I think it is an interesting post. Well formulated and easy to read and follow what you mean.
    I have not worked on key bindings myself yet, and I do not think I will have the time for it this project either. But your blog clarified a couple of things that I was not sure about.

    At first I wondered why you chose to use a std::map instead of a std::vector. My idea was that because the keys in sf::keyboard go from 0 you could just use the vectors size for the integer you have in map. But then you would have to use a fixed sized vector even if you only use seven keys. With map you is not necessary because you use the integer as the key value and the string as the mapped value.

    But what if you would have changed so instead of std::map you would use std::map? I am not so familiar with maps yet to I do not know for sure, but then you only have to change the integer to whatever the player choses. I might have gotten it all wrong, but it seems that that would be a bit more efficient or easy to understand?

    Other than that, I can’t see anything I would have done much different.

Leave a comment