Domanda

Qual è un buon modo per implementare la gestione della tastiera? In qualsiasi lingua, dove scrivo un programma interattivo da tastiera (come un gioco tetris), finisco per avere un codice simile a questo:

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)

(abbreviato). Non mi piace, dato che deve andare nel mio ciclo principale, e fa casino con tutte le parti del programma. Ciò rende anche impossibile avere una schermata di configurazione dell'utente in cui possono cambiare quali mappe chiave per quale azione. C'è un buon modello per farlo usando una qualche forma di callback di funzioni?

È stato utile?

Soluzione

È possibile creare un dizionario in cui le chiavi sono l'input e il valore è una funzione che gestisce la pressione dei tasti:

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

Quindi cambiare le chiavi è una questione di modificare le chiavi del dizionario.

Altri suggerimenti

oltre a la risposta di superjoe30 , puoi utilizzare due livelli di mappatura (due dizionari)

  • key = > stringa di comando
  • command string = > la funzione

Penso che ciò renderebbe più semplice consentire i mapping definiti dall'utente. vale a dire quindi gli utenti possono mappare le loro chiavi su " comandi " anziché " il nome di una funzione "

Quello che faccio oggi è avere una sorta di classe / funzione / thread di raccolta input che controllerà un elenco di associazioni predefinite di key > event.

Qualcosa del genere:

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

È fondamentalmente ciò che sta facendo superjoe30, tranne che invece di chiamare direttamente i callback, aggiungo un altro livello di separazione usando un sistema di dispacciamento di eventi, in modo che qualsiasi codice che si preoccupi della pressione dei tasti semplicemente ascolti quell'evento.

Inoltre, le chiavi possono essere facilmente associate a diversi eventi, che possono essere letti da un file di configurazione o qualcosa del genere e qualsiasi chiave che non è associata a un evento viene semplicemente ignorata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top