So the idea is to use functions when you want to check the state of a key, so instead of doing:
UPBGE:
ACTIVE = bge.logic.KX_INPUT_ACTIVE
W_KEY = bge.logic.keyboard.inputs[bge.events.WKEY].status[0] == ACTIVE
if W_KEY: #MyAction
BGE:
ACTIVE = bge.logic.KX_INPUT_ACTIVE
W_KEY = bge.logic.keyboard.events[bge.events.WKEY] == ACTIVE
if W_KEY: #MyAction
You do:
self.forward = keyBind(bge.events.WKEY)
# ...
if self.forward(): #MyAction
I’ve already implemented it my addon and to my surprise it is even more powerful than I though (say yes to heigher order functions). Now you can use logic bricks to configure components game keys, or you can send fake keys to a specific script.
Yup, you can make these things a lot simpler for specific use cases. One of my favourites is:
MAPPING = { # Uses strings so it can easily be loaded from files
'forward':'WKEY',
'backward':'SKEY',
'shoot':'EKEY',
}
held = bge.logic.KX_INPUT_ACTIVE
tapped = bge.logic.KX_INPUT_JUST_ACTIVATED
released = bge.logic.KX_INPUT_JUST_RELEASED
def get_key(action):
keyname = MAPPING(action)
keycode = bge.events.__dict__(keyname)
return bge.logic.keyboard.events[keycode]
if action_state('forward') is held:
do_things
if action_state('shoot') is tapped:
do_other_things
# You can also do:
if action_state('forward'):
do_things
# Because inactive is 0.....
I also have a similar function somewhere where the get_key is more general and also does mouse/joystick buttons.
On a side note, I spend the whole day today writing a system similar to javascripts DOM event handler in BGE python so I can make user interfaces really easy. It is quite a nice system, just got a few more things to finish up…
I’ve spent a lot of time writing input handlers, and would enjoy chatting about the design of this one. I’ll just have to make some documentation…
I’ve recently become a big fan of the callback approach for (amongst other things) some uses of input handling, and would be interested to know if you have a good method for registering callbacks? I have yet to make a nice callback meta-management system
from core import event
from bge import events, logic
[...]
com = object.components[n]
#Changing a key for another
com.forward = event.keyBind(events.UPARROWKEY)
#Disabling a key
com.forward = lambda: False
#Any of two keys
com.forward = lambda: event.keyPress(events.UPARROWKEY) or event.keyPress(events.UKEY)
#The default key or another:
default = com.forward
com.forward = lambda: default() or event.keyPress(events.UPARROWKEY)
#Two keys at the same time:
com.forward = lambda: event.keyPress(events.UPARROWKEY) and event.keyPress(events.UKEY)
#Joystick
com.forward = lambda: max(logic.joysticks[0].axisValues[1], 0)
com.backward = lambda: min(logic.joysticks[0].axisValues[1], 0)
#An external event
myevents["forward"] = True
[...]
com.forward = lambda: myevents["forward"]
#Another external event, a game property
com.forward = lambda: obj["forward"]
#This one even lets us use logic bricks to configure keys, for example doing:
#[Keyboard] -> [And] -> [Property: Mode(Level), Property("forward")]
Have you looked at this? What my method is caplable of and what yours is is completly diferent, to the point I feel I maybe gone a little overboard since with my method you can even make a key be pressed with a random sequence, like:
com.forward = lambda: bge.logic.getRandomFloat()
As for managing callbacks… I don’t see the problem there. Just create a list:
callbacks = []
def fun1(x): print("I'm callback 1 with arg", x)
def fun2(x): print("I'm callback 2 with arg", x)
callbacks.append(fun1)
callbacks.append(fun2)
for n in callbacks: n(x) #Where x is something.
callbacks.remove(fun1)
callbacks.remove(fun2)
The only problem there is that you can’t use lambdas, since you don’t have a reference to remove it.
To solve that you can replace the list with a dict and that would be it. You would need to put a
name to each entry tough.