Pygame:如何以多态方式编写事件循环 [英] Pygame: how to write event-loop polymorphically
问题描述
我对 pygame 有点陌生,在尝试重新开始时,我发现了用多态替换条件"的建议.大多数 pygame 教程建议使用for event in pygame.event.get()"循环,然后使用条件来确定是否发生了任何特定事件.
I'm some-what new to pygame, and while trying to get back into it, I found the advice "replace your conditionals with polymorphism." Most pygame tutorials recommend using the "for event in pygame.event.get()" loop and then using a conditional to determine if any particular event has occured.
1:如何使用多态函数编写代码2:是否值得重构代码,或者只是保持条件不变
1: How do I write that code using a polymorphic function 2: Is it worth it to re-factor the code, or just leave the conditional as-is
以下是大多数教程推荐的内容
Below is what most tutorials recommend
def gameloop():
"""
Stuff that comes before the event-loop
"""
for event in pygame.event.get():
if event.type == pygame.QUIT: # This is the conditional I want to remove
quit_functions()
下面是我想如何处理这个
Below is how I want to approach this
from abc import ABC, abstractmethod
import pygame
def detect_event(event_class_name):
for event in pygame.event.get():
# This is how I want to get the event and then assign it a function
event_class_name.determine_event(event)
# Above: I want to use this function to detect events and call their functions
# Below: This is how I want to assign functions to the events
class EventHandler(ABC):
@staticmethod
@abstractmethod
def determine_event(event): pass
class Exit(EventHandler):
@staticmethod
# How do I identify this with the event-type "pygame.QUIT," for example
def determine_event(event):
pygame.quit()
quit(0)
推荐答案
在 pygame 中,事件类型是一个枚举常量.您必须将此常量映射到相应的类.使用字典
:
In pygame the event type is an enumerator constant. You have to map this constant to the corresponding class. Use a dictionary
:
def Exit(event):
# [...]
def Keydown():
# [...]
eventhandler = {pygame.QUIT: Exit, pygame.KEYDOWN: Keydown}
当然,字典也可以动态生成甚至扩展.(例如:eventhandler[pygame.MOUSEBUTTONDOWN] = MouseDown
)
Of course, the dictionary can be generated or even extended dynamically, too. (e.g.: eventhandler[pygame.MOUSEBUTTONDOWN] = MouseDown
)
必须将事件委托给事件处理程序中分配的适当操作:
The events must be delegated to the appropriate actions assigned in the event handler:
while True:
for event in pygame.event.get():
if event.type in eventhandler:
eventhandler[event.type](event)
示例:
class EventHandler():
@staticmethod
def determine_event(event): pass
class Exit(EventHandler):
@staticmethod
def determine_event(event):
pygame.quit()
quit(0)
class Keydown(EventHandler):
@staticmethod
def determine_event(event):
print(event.key)
eventhandler = {pygame.QUIT: Exit, pygame.KEYDOWN: Keydown}
while True:
for event in pygame.event.get():
if event.type in eventhandler:
eventhandler[event.type].determine_event(event)
对于更通用的方法,可以在列表中管理处理程序.因此可以将多个操作关联到一个事件类型:
For a more general approach, the handlers can be managed in a list. So multiple actions can be associated to an event type:
def Exit(event):
# [...]
def Keydown1():
# [...]
def Keydown2():
# [...]
eventhandler = {pygame.QUIT: [Exit], pygame.KEYDOWN: [Keydown1, Keydown2]}
while True:
for event in pygame.event.get():
if event.type in eventhandler:
for target in eventhandler[event.type]:
target(event)
示例:
class EventHandler():
targets = {}
@staticmethod
def add(type, event):
EventHandler.targets.setdefault(type, []).append(event)
@staticmethod
def notify(event):
if event.type in EventHandler.targets:
for target in EventHandler.targets[event.type]:
target.determine_event(event)
@staticmethod
def determine_event(event): pass
class Exit(EventHandler):
@staticmethod
def determine_event(event):
pygame.quit()
quit(0)
class KeydownPrint(EventHandler):
@staticmethod
def determine_event(event):
print(event.key)
class KeydownAction(EventHandler):
@staticmethod
def determine_event(event):
print("action")
EventHandler.add(pygame.QUIT, Exit)
EventHandler.add(pygame.KEYDOWN, KeydownPrint)
EventHandler.add(pygame.KEYDOWN, KeydownAction)
while True:
for event in pygame.event.get():
EventHandler.notify(event)
或者甚至是两个答案的组合(见@AKX的答案):
Or even a combination of both answers (see answer of @AKX):
class EventHandler:
targets = {}
def register(type):
def decorator(fn):
EventHandler.targets.setdefault(type, []).append(fn)
return decorator
def notify(event):
fnl = EventHandler.targets[event.type] if event.type in EventHandler.targets else []
for fn in fnl:
fn(event)
@EventHandler.register(pygame.QUIT)
def onExit(event):
pygame.quit()
quit(0)
@EventHandler.register(pygame.KEYDOWN)
def keydownPrint(event):
print(event.key)
@EventHandler.register(pygame.KEYDOWN)
def keydownAction(event):
print("action")
while True:
for event in pygame.event.get():
EventHandler.notify(event)
这篇关于Pygame:如何以多态方式编写事件循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!