我刚开始玩游戏,我试着写我自己的事件管理器,因为我找不到我满意的解决方案。所以我写了我自己的灵感来自观察者模式:
from typing import Callable
from pygame.event import Event
EventHandler = Callable[[Event], None]
_managers = dict()
class EventManager:
def __init__(self, name):
self.name = name
self.handlers: dict[int, list[EventHandler]] = dict()
def notify(self, event: Event, selector=lambda event: event.type):
eventType = selector(event)
if eventType not in self.handlers:
return
for handler in self.handlers[eventType]:
handler(event)
def register(self, eventType: int, handler: EventHandler):
print(f"{self.name} registered {eventType}")
if eventType not in self.handlers:
self.handlers[eventType] = [handler]
else:
self.handlers[eventType].append(handler)
def deregister(self, eventType: int, handler: EventHandler):
if not self._is_registered(eventType, handler):
return
self.handlers[eventType].remove(handler)
def _is_registered(self, eventType, handler):
return eventType in self.handlers and handler in self.handlers[eventType]
@staticmethod
def get(id: str):
if id not in _managers:
_managers[id] = EventManager(id)
return _managers[id]
generalEventManager = EventManager.get("General Events")
keyEventManager = EventManager.get("Key Events")它是这样用的:
class Foo:
_running = True
def register_events(self):
generalEventManager.register(pygame.QUIT, lambda _: self.on_quit())
generalEventManager.register(pygame.KEYDOWN, lambda event: self.on_key_down(event))
# register key events with
# keyEventManager.register(pygame.K_RETURN, lambda _: self.on_k_return())
# ...
def on_key_down(self, event: Event):
keyEventManager.notify(event, selector=lambda event: event.key)
def on_quit(self):
self._running = False
def on_cleanup(self):
pygame.quit()
def on_execute(self):
while self._running:
for event in pygame.event.get():
self.on_event(event)
self.on_cleanup()这是毕多尼亚人吗?在游戏中有没有更好的解决方案?有没有我没有找到的通用python库解决方案?
发布于 2022-07-25 21:56:21
这看上去相当像琵琶,并且很好地利用了观察者的模式。
我要说的一件事是,对于备用构造函数,您通常使用类方法而不是静态方法,然后调用'cls‘属性,而不是按名称调用类。如果您想要使用继承,这一点很重要,此外,出于同样的原因,您可能希望将您的_managers全局dict绑定到该类。
@classmethod
def get(cls, id: str):
if id not in cls._managers:
cls._managers[id] = cls(id)
return cls._managers[id]此外,您不需要每次都通过lambdas。您可以直接传递函数本身。
def register_events(self):
generalEventManager.register(pygame.QUIT, self.on_quit) # You'll need to modify the call signature here
generalEventManager.register(pygame.KEYDOWN, self.on_key_down)
# register key events with
# keyEventManager.register(pygame.K_RETURN, self.on_k_return)
# ...您的名字有点不具有描述性,我可能会将您的'get‘方法称为'from_id’之类的方法,以表示清晰,而且很明显,'Foo‘应该更丰富一些。
我还将研究处理其他高阶函数的更好方法,而不是依赖lambdas。例如,可以尝试使用操作符模块:
from operator import attrgetter
# Code here
def notify(self, event: Event, selector=attrgetter('type')):
...此外,您可能希望使用默认的dict来稍微简化实现:
from collections import defaultdict
from operator import attrgetter
class EventManager:
def __init__(self, name):
self.name = name
self.handlers: dict[int, list[EventHandler]] = defaultdict(list)
def notify(self, event: Event, selector=attrgetter('type')):
for handler in self.handlers[selector(event)]:
handler(event)
def register(self, eventType: int, handler: EventHandler):
print(f"{self.name} registered {eventType}")
self.handlers[eventType].append(handler)
def deregister(self, eventType: int, handler: EventHandler):
if handler in self.handlers[eventType]:
self.handlers[eventType].remove(handler)
@classmethod
def from_id(cls, _id: str):
if _id not in _managers:
_managers[_id] = EventManager(_id)
return _managers[_id]https://codereview.stackexchange.com/questions/278341
复制相似问题