Frage

I was planning on doing a little crossplatform game with kivy and, when I was testing the way to get input from the keyboard on the pc, I had a little surprise.

Kivy doesn't seem to handle several keys pressed at same with it's on_keyboard_down events, when you press more than one key at same in kivy, the keyboard class used in the official documentation passes the last pressed key in change of all the keys being pressed at the moment.

It looks like the keyboard class is designed to let the user type in the app because when you press a key for seconds, there's a little delay between the first key event and the rest of them (which are finally one per step), just like the one you can notice when typing.

This is the code I wrote for a keyboard-interactive hello world.

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.scatter import Scatter
from kivy.core.window import Window

class MyApp(App):
    def __init__(self, **kwargs):
        super(MyApp, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down = self._on_keyboard_down)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down = self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        print str(keyboard)+' '+str(keycode[1])+' '+str(text)+' '+str(modifiers)
        if keycode[1] == 'w':
            self.moveable.y += 1

        if keycode[1] == 's':
            self.moveable.y -= 1

        if keycode[1] == 'd':
            self.moveable.x += 1

        if keycode[1] == 'a':
            self.moveable.x -= 1 


    def build(self):
        self.moveable = Scatter()
        self.moveable.add_widget( Label(text = 'Hello moving world!') )
        return self.moveable

if __name__ == '__main__':
    MyApp().run()

Because of what I wrote before, this doesn't seem like the kind of keyboard input I'd use for a video game, and I haven't found anywhere how to get it better for that purpose.

Sorry if the question is inappropiate for some reason, I tried to find the answer to this, but I couldn't, so here it is.

Thanks you a lot in advance if you can help with it.

War es hilfreich?

Lösung

It looks like the keyboard class is designed to let the user type in the app because when you press a key for seconds, there's a little delay between the first key event and the rest of them

(Edit: Having reread your post, I think you don't want to change this at all and have misunderstood how to work with keyboard input, see the second part of this post)

I'm pretty sure this is down to operating system settings, not to do with Kivy. There's plenty of discussion about changing this value online if you want to, for instance on linux you can probably do xset r rate [delay] [rate], e.g. xset r rate 200 25, or in various desktop environments there's a gui setting for it. Similar things are true on windows. The keyword seems to be 'repeat delay'.

That said, I'm not sure why this actually matters. Kivy tells you when the key is pressed and when it is released, and you can perform an event however often you like during that time if you want to. Why does it matter whether the os keeps sending you extra keypresses?

Kivy doesn't seem to handle several keys pressed at same with it's on_keyboard_down events, when you press more than one key at same in kivy, the keyboard class used in the official documentation passes the last pressed key in change of all the keys being pressed at the moment.

I think you might be misunderstanding how Kivy is presenting you this information. When a key is pressed, kivy passes you an on_key_down event for that key. When it is released, kivy passes an on_key_up event for that key (your program doesn't do anything with this). In between those events you know the key is still pressed, it doesn't matter whether the system keeps feeding you fake keypresses.

Edit: Here is a modified version of your program that prints on_key_up event information as well:

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.scatter import Scatter
from kivy.core.window import Window

class MyApp(App):
    def __init__(self, **kwargs):
        super(MyApp, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down = self._on_keyboard_down)
        self._keyboard.bind(on_key_up = self._on_keyboard_up)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down = self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, *args):
        print 'down', args

    def _on_keyboard_up(self, *args):
        print 'up', args


    def build(self):
        self.moveable = Scatter()
        self.moveable.add_widget( Label(text = 'Hello moving world!') )
        return self.moveable

if __name__ == '__main__':
    MyApp().run()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top