2008-11-23 48 views
9

什麼是實現鍵盤處理的好方法?在任何一種語言,當我寫一個鍵盤交互程序(如俄羅斯方塊遊戲),我最終有一些代碼,看起來像這樣:有效的鍵盤輸入處理

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

回答

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

3

除了superjoe30's answer,您可以使用映射的兩個級別(兩個庫)

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

我認爲這將使它更容易允許用戶定義的映射。即使用戶可以將他們的鍵映射到「命令」而不是「功能的名稱」

2

我現在所做的是有某種輸入收集類/函數/線程,它將檢查預定義的鍵列表 - >事件綁定。

事情是這樣的:

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正在做,但不是直接調用回調,我使用事件調度系統添加分離的另一個層面,因此任何代碼,關心按下的按鍵只是聽該事件。另外,鍵可以很容易地綁定到不同的事件上,這些事件可以從配置文件或其他東西中讀取,任何未綁定到事件的鍵都會被忽略。