Key and mouse bindings

Hello,

- Added: a converted build for UPBGE (4-3-2019)

Let the user/player set his own key and mouse bindings.

How it works:

  • On a press of a button the script listen to our keyboard and mouse, once we get an input we put it into the global dict.
  • The global dict is used to save, load and use all the keybindings.

How to use:

  • Hit K to open the keybindings menu.
  • Click on a button to set a new key or mouse button.
  • Hit save or the close button to save and close the menu

How to port it to your game:

  • Import the empty from the main scene into your main scene.
  • Import the keybindings scene into your blend file (file->append).
  • Make sure you have keybindings.py and my_functions.py aswell.
  • Go to keybindings.py and change the scene names at the top of the script

How to add more Buttons/keys:

  • Select 1 button and the text object, duplicate it, change the property to your likings
  • Now go to keybindings.py head to def default_keybindings(cont): and set the key there as well
  • Done!

Key and mouse bindings in action: (showing older version, but you get the idea)

BGE:
key and mouse bindings.blend (689.4 KB)
(Ignore the last comment in the Readme, forgot to remove it)

UPBGE:
keybindings upbge.blend (785.6 KB)

if you need a ‘First Person View’ movement script attached to it (BGE/UPBGE):

if you need a ‘Third Person View’ movement script attached to it (BGE/UPBGE):

As always if you like it or gonna use it leave a reply/like, thanks!

Cotaks

Very nice!

Where do I get this ??? keybindings.py and my_functions.py

They are included in the blend file. you can just copy/paste the scripts and put it in your blend.
or you can append it into your blend
or you can save the scripts as a file and then load it in your blend.

i have created a very simple movement with your key bindings, it work fine but there is a error in console say: ( KeyError: ‘key bindings’ )
how i can fix this? thank you

Attachments

keybindings_error.zip (98.6 KB)

You should find this error on your own, if you compare yours with my setup.
keyError means the the word that you are searching in the GD does not exist(keybindings)

That’s why i have a check in my_functions called check_GD(gd_name)
And that is why i also placed they keys in an if statement to check if the gd is really loaded.

So to fix the error, replace your code with this.


        GD = check_GD('keybindings')
        
        if GD: #<- this will fail on the first frame
            # get key status 1 = just_activated, 2 = pressed, 0 = False
            forwards    = key_status(GD['forwards'])
            backwards   = key_status(GD['backwards'])
            left        = key_status(GD['strafe_left'])
            right       = key_status(GD['strafe_right'])
            run         = key_status(GD['run'])
            jump        = key_status(GD['jump']) == 1
        else:
            return #<- so we get here, and tell it to go out of this function, next frame it runs the script again and all will succeed, because the GD is now really loaded and ready to be used

OR instead of having the keys in an if statement you can also do:


        GD = check_GD('keybindings')
        
        if not GD:
            return
        
        # get key status 1 = just_activated, 2 = pressed, 0 = False
        forwards    = key_status(GD['forwards'])
        backwards   = key_status(GD['backwards'])
        left        = key_status(GD['strafe_left'])
        right       = key_status(GD['strafe_right'])
        run         = key_status(GD['run'])
        jump        = key_status(GD['jump']) == 1

and add the check_GD function in your script as well


def check_GD(name):
    
    GD = logic.globalDict
        
    if not GD:
        print('*** NO GD/SAVE file found! ***')
        return
    
    elif not name in GD:
        print('No GD['+ name +'] found')
        return
    
    else:
        return GD[name]

Simply said, the GD needs 1 frame to load in, so in the first frame the script can’t get the controls, thats why we call a function to check the gd and return it, then in the script the check wil put the movement on hold for 1 frame, so the GD can be loaded in correctly.

sorry my python knowledge is weak, if i do like this it don’t work so how the all script should be?



#################################################
#                                               #
#           MOVEMENT SCRIPT BY COTAX            #
#                 Blender 2.6+                  #
#                                               #
####################"############################
from bge import logic, events, render 




def key_status(key_event):
    
    # get the active states of a keypress
    # example: Key_event is a keyname like WKEY for w  
    
    active_keys = logic.keyboard.active_events
    keycode = events.__dict__[key_event]
   
    return active_keys.get(keycode, 0)


 
def player():


    cont    = logic.getCurrentController()
    scene   = logic.getCurrentScene()
    
    own     = cont.owner
    
    walk = cont.actuators['walk']
    back = cont.actuators['back']
    Lturn = cont.actuators['Lturn']
    Rturn = cont.actuators['Rturn']


    # Run the script or not
    if own['movement_script'] == True: 
        
        GD = check_GD('keybindings')
        
        if not GD:
            return
        
        # get key status 1 = just_activated, 2 = pressed, 0 = False
        forwards    = key_status(GD['forwards'])
        backwards   = key_status(GD['backwards'])
        left        = key_status(GD['strafe_left'])
        right       = key_status(GD['strafe_right'])
        run         = key_status(GD['run'])
        left_click  = key_status(GD['keybindings']['left_click'])
        
def check_GD(name):
       
    GD = logic.globalDict
        
    if not GD:
        print('*** NO GD/SAVE file found! ***')
        return
    
    elif not name in GD:
        print('No GD['+ name +'] found')
        return
    
    else:
        return GD[name]
            
        if forwards:
            cont.activate(walk)
        else:
            cont.deactivate(walk)
        
        if backwards:
            cont.activate(back)
        else:
            cont.deactivate(back)
        
        if left:
            cont.activate(Lturn)
        else:
            cont.deactivate(Lturn)
        
        if right:
            cont.activate(Rturn)
        else:
            cont.deactivate(Rturn) 

and please why mouse key can be added to forwards,backwards…etc but it don’t trigger actuators?

you shared thisKeybindings with fpv movement script but it would be great if you share a Key and mouse bindings .blend with your movement.py

thank for your time :slight_smile:


from bge import logic, events, render 




def key_status(key_event):
    
    # get the active states of a keypress
    # example: Key_event is a keyname like WKEY for w  
    
    active_keys = logic.keyboard.active_events
    keycode = events.__dict__[key_event]
   
    return active_keys.get(keycode, 0)


 
def player():


    cont    = logic.getCurrentController()
    scene   = logic.getCurrentScene()
    
    own     = cont.owner
    
    walk = cont.actuators['walk']
    back = cont.actuators['back']
    Lturn = cont.actuators['Lturn']
    Rturn = cont.actuators['Rturn']


    # Run the script or not
    if own['movement_script'] == True: 
        
        # get the sensors.
       
        GD = logic.globalDict
        
        if not GD:
            return


        # get key status 1 = just_activated, 2 = pressed, 0 = False
        forwards    = key_status(GD['keybindings']['forwards'])
        backwards   = key_status(GD['keybindings']['backwards'])
        left        = key_status(GD['keybindings']['strafe_left'])
        right       = key_status(GD['keybindings']['strafe_right'])
        run         = key_status(GD['keybindings']['run'])
        jump        = key_status(GD['keybindings']['jump']) == 1
        
        if forwards:
            cont.activate(walk)
        else:
            cont.deactivate(walk)
        
        if backwards:
            cont.activate(back)
        else:
            cont.deactivate(back)
        
        if left:
            cont.activate(Lturn)
        else:
            cont.deactivate(Lturn)
        
        if right:
            cont.activate(Rturn)
        else:
            cont.deactivate(Rturn) 

this will work also, just added: if not GD: return

You only needed to replace the lines in your script with what i have posted, your script the the activation of controllers you placed it within the check_GD that will not work indeed.

you had forgotten to remove keybindings and placed the controls the wrong position
here the code with check_GD


#################################################
#                                               #
#           MOVEMENT SCRIPT BY COTAX            #
#                 Blender 2.6+                  #
#                                               #
####################"############################
from bge import logic, events, render 








def key_status(key_event):
    
    # get the active states of a keypress
    # example: Key_event is a keyname like WKEY for w  
    
    active_keys = logic.keyboard.active_events
    keycode = events.__dict__[key_event]
   
    return active_keys.get(keycode, 0)


def check_GD(name):
       
    GD = logic.globalDict
        
    if not GD:
        print('*** NO GD/SAVE file found! ***')
        return
    
    elif not name in GD:
        print('No GD['+ name +'] found')
        return
    
    else:
        return GD[name]
 
def player():




    cont    = logic.getCurrentController()
    scene   = logic.getCurrentScene()
    
    own     = cont.owner
    
    walk = cont.actuators['walk']
    back = cont.actuators['back']
    Lturn = cont.actuators['Lturn']
    Rturn = cont.actuators['Rturn']




    # Run the script or not
    if own['movement_script'] == True: 
        
        GD = check_GD('keybindings')
        
        if not GD:
            return
        
        # get key status 1 = just_activated, 2 = pressed, 0 = False
        forwards    = key_status(GD['forwards'])
        backwards   = key_status(GD['backwards'])
        left        = key_status(GD['strafe_left'])
        right       = key_status(GD['strafe_right'])
        run         = key_status(GD['run'])
        left_click  = key_status(GD['left_click'])
        
        if forwards:
            cont.activate(walk)
        else:
            cont.deactivate(walk)
        
        if backwards:
            cont.activate(back)
        else:
            cont.deactivate(back)
        
        if left:
            cont.activate(Lturn)
        else:
            cont.deactivate(Lturn)
        
        if right:
            cont.activate(Rturn)
        else:
            cont.deactivate(Rturn)  



thank you very much. i really appreciate, and please why mouse key can be added to forwards,backwards…etc but it don’t trigger actuators?

you shared thisKeybindings with fpv movement script, i hope you will share a Key and mouse bindings .blend with your movement.py soon

because your key_status is only doing the keyboard check.

replace your def key_status(key_event):

with


def key_status(key_event):
        
    mouse_events    = logic.mouse.active_events
    keyboard_events = logic.keyboard.active_events
    
    keycode         = events.__dict__[key_event]


    if keycode in mouse_events:       
        active_keys = mouse_events                 
    else:
        active_keys = keyboard_events
            
    return active_keys.get(keycode, 0)

Your welcome

#EDIT
I see you used both of the keybindings scripts to make one script, that is where it went wrong.

-ADDED: the same movement script as the ‘keybind only’ script has. located in #1 Post

big thanks

good work, but i hate the fact that we can’t rename the scene or use this Key bindings in other scenes, because the name must be ‘scene’ or the script don’t work correctly.

No lol, just change the scene name in the script (like said in the readme) to the scene names you are using.

and when player is moving from scene to other scene can we still use Key bindings, or it work only for one scene that we add in keybindings.py top script?

you can adjust it in a few ways.

  1. change this line: main_scene = ‘Scene’ into: main_scene = own.scene (also add the line that create the own)
  2. convert main_scene = ‘Scene’ into a property and change it when you switch scenes
  3. remove the main_scene = ‘Scene’ and 2 the lines that uses it, and replace it with bricks, so you can add/remove the scene with that.
  4. use the GD to save the scene name that you are using, it’s the same as with property but then using the GD.
  5. use libload to load in the blends/levels, so you never need to change a scene (recommended)
  6. anyway you like.

new version 2.1

  • added double input check, only 1 key per bind allowed in this version.

I designed version 2.0 to be able to set more actions for 1 key, some people don’t like this option so i created v2.1 specially for them.

good work on this, some players don’t speak english and some players are still kids can mistakenly use the same key for forward and jump for example. and change the gameplay to a bunny dance!, BGE users can chose to use the 2.1 version to avoid one key mistake. thank you for putting this in resources

after downloading and try it i must say this still can be improved more than this.
right now when you try to use a key already in use nothing change that’s good but it’s better to make the new key use overwrite the used key, for example if W key is used for jump if we press W for forward the W is removed from jump.

right now if W key is used for jump to change W key to forward first we must change the jump to an unused key then we can change the forward key to W

the need to first free the used key to use it in different action will bother players