有效的键盘输入处理

问题描述:

什么是实现键盘处理的好方法?在任何一种语言,当我写一个键盘交互程序(如俄罗斯方块游戏),我最终有一些代码,看起来像这样:有效的键盘输入处理

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) 

(缩短)。我不喜欢这一点,因为这必须在我的主循环中进行,并且会与程序的所有部分混淆。这也使得不可能拥有用户配置屏幕,他们可以在哪里更改哪些键映射到哪个操作。有没有一种很好的模式来使用某种形式的函数回调?

+0

另请参阅http://stackoverflow.com/questions/292095/polling-the-keyboard-in-python – 2008-11-23 12:40:17

您可以创建一个字典,其中键是输入和值是处理按键的功能:

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

然后改变键是修改字典的键的问题。

+0

我不确定,但我相信这些函数defs必须去*分支的分配,否则你会得到一个充满了Nones的字典。好的回答,但这也可能是我会这么做的。 – luqui 2008-11-23 08:04:19

+0

我想这些仍然必须在main()循环中定义 - 或者可能需要一些GameState类的参数 – Claudiu 2008-11-24 01:59:42

+0

维护逆字典可能会更好:`func2keys = {handle_quit:[K_q],handle_left:[ K_LEFT,K_a],...}。如果配置更改,则生成一个新的“分支”字典。 `分支= dict((k,f)为f,键为func2keys.items(),键为k)` – jfs 2008-11-30 02:25:09

除了superjoe30's answer,您可以使用映射的两个级别(两个库)

  • 键=>命令字符串
  • 命令串=>功能

我认为这将使它更容易允许用户定义的映射。即使用户可以将他们的键映射到“命令”而不是“功能的名称”

我现在所做的是有某种输入收集类/函数/线程,它将检查预定义的键列表 - >事件绑定。

事情是这样的:

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正在做,但不是直接调用回调,我使用事件调度系统添加分离的另一个层面,因此任何代码,关心按下的按键只是听该事件。另外,键可以很容易地绑定到不同的事件上,这些事件可以从配置文件或其他东西中读取,任何未绑定到事件的键都会被忽略。