Пиглет обнаруживает, когда клавиша не была нажата в предыдущем кадре - PullRequest
0 голосов
/ 11 апреля 2020

Я сейчас играю в pyglet, и у меня есть настройки клавиш:

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 update(self, keys, dt):
    if (key.UP in keys) & (key.UP not in self.prev_keys):
        jump()
self.prev_keys = keys

Но они всегда равны, что бы ни случилось. Я не могу определить, когда они впервые удерживают клавишу. Если вам нужна дополнительная информация о том, что я пытаюсь сделать или как настроен мой код, просто спросите. Спасибо за помощь!

РЕДАКТИРОВАТЬ: Хорошо, я понял, в чем моя проблема. В дополнение к ответу Torxed ниже (об использовании & vs. и) моя главная проблема заключалась в том, что объекты словаря были связаны. Итак, вместо self.prev_keys = keys мне нужно использовать self.prev_keys = keys.copy(). Надеюсь, что это поможет любому с той же проблемой, что и я!

1 Ответ

1 голос
/ 17 апреля 2020

Итак, ваша основная проблема , вероятно использование & вместо and здесь:

if (key.UP in keys) & (key.UP not in self.prev_keys):

Потому что побитовое И (&) - это не то же самое, что И оператор (and) . & фактически сравнивается на битовом уровне, если один или несколько 1 совпадают друг с другом. Вот упрощенный пример того, как двоичные числа работают и как побитовое И (&) работает с / на них:

00000001  # Value 1
00000011  # Value 3

Выполнение 1 & 3 приведет к 1, потому что на уровне битов 1 находятся в одном и том же «местоположении». Где, как показано в следующем примере:

00000001  # Value 1
00000100  # Value 4

Выполнение 1 & 4 приведет к 0, поскольку 1 выровнено вниз.

Вы пытаетесь сравнить, если оба если операторы истинны if (...) and (...), используя бит-уровень-компаратор. Который не будет работать. Таким образом, решение здесь будет следующим:

if (key.UP in keys) and (key.UP not in self.prev_keys):

Таким образом, код может выглядеть примерно так:

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.processed_keys = {}

        self.mouse_x = 0
        self.mouse_y = 0

        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()

        ## Add stuff you want to render here.
        ## Preferably in the form of a batch.

        self.flip()

    def jump(self):
        print('Jumped, yaay!')

    def update(self):
        if (key.UP in self.keys) and (key.UP not in self.processed_keys):
            self.jump()

        self.processed_keys = {**self.keys}

    def run(self):
        while self.alive == 1:
            self.update()
            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()
...