Эффективная обработка ввода с клавиатуры - PullRequest
9 голосов
/ 23 ноября 2008

Какой хороший способ реализовать обработку клавиатуры? На любом языке, где я пишу интерактивную клавиатуру (например, игру в тетрис), я получаю код, который выглядит следующим образом:

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)

(укороченный). Мне это не нравится, так как это должно идти в моем основном цикле, и это портит все части программы. Это также делает невозможным создание пользовательского экрана конфигурации, на котором они могут изменить какие карты ключей и на какое действие. Есть хороший шаблон, чтобы сделать это с помощью какой-либо функции обратного вызова функции?

Ответы [ 3 ]

17 голосов
/ 23 ноября 2008

Вы можете создать словарь, в котором клавиши являются вводом, а значение является функцией, которая обрабатывает нажатие клавиши:

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

Тогда изменение ключей - это вопрос изменения ключей словаря.

3 голосов
/ 23 ноября 2008

в дополнение к ответу superjoe30 , вы можете использовать два уровня отображения (два словаря)

  • key => строка команды
  • командная строка => функция

Я думаю, это упростит разрешение пользовательских сопоставлений. то есть пользователи могут сопоставить свои ключи с «командами», а не с «именем функции»

2 голосов
/ 24 ноября 2008

В настоящее время я делаю что-то вроде класса / функции / потока сбора данных, который будет проверять список предопределенных привязок клавиш-> событий.

Примерно так:

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

Это в основном то, что делает superjoe30, за исключением того, что вместо прямого обратного вызова я добавляю другой уровень разделения с помощью системы диспетчеризации событий, чтобы любой код, который заботится о нажатых клавишах, просто прослушивал это событие.

Кроме того, ключи могут быть легко привязаны к различным событиям, которые могут быть прочитаны из файла конфигурации или чего-либо еще, и любой ключ, который не связан с событием, просто игнорируется.

...