Pregunta

¿Cuál es una buena manera de implementar el manejo del teclado? En cualquier idioma, donde escribo un programa interactivo con el teclado (como un juego de tetris), termino teniendo un código similar al siguiente:

for event in pygame.event.get():
    if event.type == KEYDOWN:
        if False: pass          #make everything an elif
        elif rotating: pass
        elif event.key == K_q:
        elif event.key == K_e:
        elif event.key == K_LEFT:
            curpiece.shift(-1, 0)
            shadowpiece = curpiece.clone(); setupshadow(shadowpiece)
        elif event.key == K_RIGHT:
            curpiece.shift(1, 0)
            shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

(acortado). No me gusta esto, ya que esto tiene que ir en mi bucle principal, y se mete con todas las partes del programa. Esto también hace que sea imposible tener una pantalla de configuración de usuario donde puedan cambiar las asignaciones de teclas a las acciones. ¿Hay un buen patrón para hacer esto usando alguna forma de devolución de llamada de función?

¿Fue útil?

Solución

Podría crear un diccionario donde las teclas son la entrada y el valor es una función que maneja la pulsación de teclas:

def handle_quit():
  quit()

def handle_left():
    curpiece.shift(-1, 0)
    shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

def handle_right():
    curpiece.shift(1, 0)
    shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

def handle_pause():
    if not paused:
        paused = True

branch = {
  K_q: handle_quit
  K_e: handle_pause
  K_LEFT: handle_left
  K_RIGHT: handle_right
}

for event in pygame.event.get():
    if event.type == KEYDOWN:
        branch[event.key]()

Luego, cambiar las claves es una cuestión de modificar las claves del diccionario.

Otros consejos

además de respuesta de superjoe30 , puede usar dos niveles de mapeo (dos diccionarios)

  • clave = > cadena de comando
  • cadena de comando = > función

Creo que esto facilitaría la asignación de asignaciones definidas por el usuario. es decir, para que los usuarios puedan asignar sus teclas a "comandos" en lugar de " el nombre de una función "

Lo que hago hoy en día es tener algún tipo de clase / función / subproceso de recopilación de entradas que verificará una lista de enlaces de eventos predefinidos de teclas >

Algo como esto:

class InputHandler:
    def __init__ (self, eventDispatcher):
        self.keys = {}
        self.eventDispatcher = eventDispatcher
    def add_key_binding (self, key, event):
        self.keys.update((key, event,))
    def gather_input (self):
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                event = self.keys.get(event.key, None)
                if not event is None:
                    self.eventDispatcher.dispatch(event)

....
inputHandler = InputHandler(EventDispatcher)
inputHandler.add_key_binding(K_q, "quit_event")
...
inputHandler.gather_input()
....

Es básicamente lo que está haciendo superjoe30, excepto que en lugar de llamar a las devoluciones de llamada directamente, agrego otro nivel de separación mediante el uso de un sistema de despacho de eventos, de modo que cualquier código que se preocupe por las teclas presionadas simplemente escuche ese evento.

Además, las claves pueden vincularse fácilmente a diferentes eventos, que podrían leerse desde un archivo de configuración o algo y cualquier clave que no esté vinculada a un evento simplemente se ignora.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top