1

I have been trying to use some "key released" functions from libraries like pynput and so, but I ran in to the problem that if I try using them together with a library called pyglet, that is a library for window-based apps, it won't let me and the program would crash.

I was wondering if there is any way detect key releases without libraries.

P.S: I've tried using the on_key_release function from pyglet but it was buggy for me and even though I wrote something for it to upon key release it usually didn't do it. I have checked my code a thousand times and it's not a problem on my part.

Pressing = False # var to indicate when the user is doing a long press and when he is not
@window.event
def on_key_release(symbol, modifiers):
    global Pressing
    if((symbol == key.A) | (symbol == key.S) | (symbol == key.W) | (symbol == key.D)):
        Pressing = False
    pass

and that code causes my player to freeze after i start moving him, and it does this even if i do nothing and just leach the whole on_key_release dunction empty. really weird.

  • This sounds like a [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). You should probably ask why it was buggy with Pyglet instead of trying to patch in more problems to solve your original problem. `on_key_release` has never been buggy for me (see my other answer on your [other problem](https://stackoverflow.com/a/58500680/929999) for an example code) – Torxed Oct 22 '19 at 09:07
  • ok thanks :) will try that – Elamar Kaodsh Oct 22 '19 at 20:30
  • Could you perhaps paste your `on_key_release` code as well? And if possible, paste a minimal executable example that we can run/try with? – Torxed Oct 23 '19 at 12:12
  • Ah, so the problem is that the character freezes? I see why if so, `on_key_release` is when you're releasing **any key**, and since you're no longer holding down `A` for instance, `S`, `W` and `D` will be `False` too. I could give you a quick example of how you should do it instead if you want to. – Torxed Oct 23 '19 at 13:43

1 Answers1

1

So, your issue is most likely that you're doing Pressing = False if any key is released. Forcing your player object to freeze due to Pressing being False as soon as you release any of your keys.

To work around this, you should store the states of your keys in a variable (I'll call it self.keys), and just before you render stuff, update/check the keys and update your player object accordingly.

Here's a working example of movement on a player object (a red square in this case):

from pyglet import *
from pyglet.gl import *

key = pyglet.window.key

class main(pyglet.window.Window):
    def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
        super(main, self).__init__(width, height, *args, **kwargs)
        self.x, self.y = 0, 0

        self.keys = {}

        self.mouse_x = 0
        self.mouse_y = 0

        square = pyglet.image.SolidColorImagePattern((255, 0, 0, 255)).create_image(40, 40)
        self.player_object = pyglet.sprite.Sprite(square, x=self.width/2, y=self.height/2)

        self.alive = 1

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_mouse_motion(self, x, y, dx, dy):
        self.mouse_x = x

    def on_key_release(self, symbol, modifiers):
        try:
            del self.keys[symbol]
        except:
            pass

    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE: # [ESC]
            self.alive = 0

        self.keys[symbol] = True

    def render(self):
        self.clear()

        ## Movement logic,
        #  check if key.W is in self.keys (updated via key_press and key_release)
        if key.W in self.keys:
            self.player_object.y += 1
        if key.S in self.keys:
            self.player_object.y -= 1
        if key.A in self.keys:
            self.player_object.x -= 1
        if key.D in self.keys:
            self.player_object.x += 1

        self.player_object.draw()

        self.flip()

    def run(self):
        while self.alive == 1:
            self.render()

            # -----------> This is key <----------
            # This is what replaces pyglet.app.run()
            # but is required for the GUI to not freeze
            #
            event = self.dispatch_events()

if __name__ == '__main__':
    x = main()
    x.run()

I've moved away from @window.event because it's easier for me to just copy paste this class/inheritance example since I had it laying around. But you could apply this logic any way you want. Just make sure you don't defined a solid state of pressing or not pressing, check individual keys and update accordingly before you render.

Torxed
  • 22,866
  • 14
  • 82
  • 131