# Customized controls per player for local multiplayer / coop

Attention Topic was automatically imported from the old Question2Answer platform.
Asked By st_phan

Context:

• I am making a local coop/multiplayer game
• I want to allow key rebinding due to accessibility (and player preference)
• → It can be the case that e.g. two gamepads are connected, but with different control schemes

Problem:
Godot’s input map doesn’t allow to specify anything per player.

Question:
Is there a best practice or recommendation to approach this?
Thanks in advance <3

Reply From: zhyrin

This video has a solution: https://www.youtube.com/watch?v=tkBgYD0R8R4

Thank you for the answer.

If I haven‘t missed anything, the solution is based on creating input map entries for each player (e.g. `run_player_1` and `run_player_2`).

While that works, it‘s uglier and less scalable than a solution I‘d hope for.

st_phan | 2023-06-22 19:50

How do you expect a solution to be prettier and more scalable?
I think this is as good as it gets. There is a finite number of players that can be handled on a local machine anyway.

zhyrin | 2023-06-23 10:32

In the issue I linked to above there is quite an extensive discussion on how the input system could be majorly enhanced (if Godot’s core would be expanded) – check it out, it’s interesting, especially this comment.

I posted my question to see if I had missed an obvious approach that is fairly flexible (like the proposed stuff in the issue).

st_phan | 2023-06-23 10:52

Reply From: godot_dev_

I have solved this before and will help by providing a coding example immediatly below and will then explain the logic aftewards

``````const BTN_A = 1 #(BIT SHIFT 0) 0001 in binary, 1 decimal
const BTN_B = 1 << 1 # 0010 in binary, 2 deciaml
const BTN_X = 1 << 2 # 0100 in binary, 4 decimal

const BTN_A_KEY = "A"
const BTN_B_KEY = "B"
const BTN_X_KEY = "X"

var btnMap = {}
var pInRemap  = {}

func _ready():
#initialize button map
btnMap[BTN_A_KEY] = BTN_A
btnMap[BTN_B_KEY] = BTN_B
btnMap[BTN_X_KEY] = BTN_X

#no remapping by default
for k in btnMap.keys():
pInRemap[k]=btnMap[k]

#targetBtn is a string representing button (will be used as key to access the button maps)
#newBtns is an array of strings, representing the buttons to map to when pressing target button
func remapButton(targetBtn, newBtns):

if (targetBtn == null):
return

var btnCode =null

#only compute the button bit maps for none empty remapping
if newBtns != null and newBtns.size() > 0:
btnCode=0
#go set all bits of btnCode, for each new button
for b in newBtns:
btnCode = btnCode | btnMap[b]

#remap
pInRemap[targetBtn] = btnCode

#example of remapping the A button to be a macro of 'B+X'
remapButton(BTN_A_KEY,[BTN_B,BTN_X])

func processInput():

#suppose the way you mapped your buttons is a 2 player game as follows:
#"P1_A": the "A" button for player 1
#"P2_A": the "A" button for player 2
#"P1_X": the "X" button for player 1
#"P2_X": the "X" button for player 2
#etc.
var inputDeviceIds = ["P1","P2"]

for inputDeviceId in inputDeviceIdS:
var inputJustPressedBitMap = 0
var btnKeys = pInRemap.keys()
#iterate all buttons to create bit map
for k in btnKeys:

#remapping of buttons made it so a button maps to no input?
if pInRemap[k] == null:
continue
#tranlate button id to device button (2 different devices have same button)
#differentiate devices via inputDevice id. Needd to map this in input seetings
var inputId = inputDeviceId+"_"+k
#check if player just pressed it
if Input.is_action_just_pressed(inputId):

inputJustPressedBitMap = inputJustPressedBitMap | pInRemap[k]

#take bit-wise-and operator to determine whether button was pressed
if (inputJustPressedBitMap & BTN_A) ==BTN_A:
#player <inputDeviceId> pressed a button that maps to button A
pass
if (inputJustPressedBitMap & BTN_B) ==BTN_B:
#player <inputDeviceId> pressed a button that maps to button B
pass
if (inputJustPressedBitMap & BTN_X) ==BTN_X:
#player <inputDeviceId> pressed a button that maps to button X
pass
``````

The idea is that a dictionary maps action input names to button bitmap codes (each button has its own unique bit set to 1). This way, you can represent a series of button presses with a single integer variable. For example, in the above code

001 = would be treated as button A was pressed
101 = would be treated as button A and X were pressed together

This then allows to you create a dictionary that remaps a raw button press to null input, another input, or a macro of inputs

Thanks for sharing, this is quite a unique an interesting approach!

st_phan | 2023-06-23 10:53

Oops, just realize there is a small bug in the code I provided. Each player should have their own script with a `inputDeviceId`, so that each player would have a button remaps dictionaries (so the for loop that iterates the input device names would be unecessary in the `processInput` fucntion)

godot_dev_ | 2023-06-23 15:36