首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Pygame:如何以多形性方式编写事件循环

Pygame:如何以多形性方式编写事件循环
EN

Stack Overflow用户
提问于 2020-02-26 04:09:44
回答 3查看 431关注 0票数 2

我是一些-什么新的游戏,当我试图回到它,我发现建议“用多态取代你的条件。”大多数游戏教程建议使用“pygame.event.get()中的事件”循环,然后使用条件来确定是否发生了任何特定事件。

1:如何使用多态函数编写代码? 2:是否值得重新分析代码,还是只保留条件不变?

下面是大多数教程推荐的内容

代码语言:javascript
复制
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()

下面是我如何处理这个问题的方法

代码语言:javascript
复制
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)
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-02-26 07:39:06

在吡咯中,事件类型是枚举数常量。您必须将这个常量映射到相应的类。使用dictionary

代码语言:javascript
复制
def Exit(event):
    # [...]

def Keydown():
    # [...]

eventhandler = {pygame.QUIT: Exit, pygame.KEYDOWN: Keydown}

当然,字典也可以动态生成甚至扩展。(例如:eventhandler[pygame.MOUSEBUTTONDOWN] = MouseDown)

必须将事件委托给事件处理程序中分配的适当操作:

代码语言:javascript
复制
while True:
    for event in pygame.event.get():
        if event.type in eventhandler:
            eventhandler[event.type](event)

示例:

代码语言:javascript
复制
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)

对于更一般的方法,可以在列表中管理处理程序。因此,可以将多个操作关联到一个事件类型:

代码语言:javascript
复制
def Exit(event):
    # [...]

def Keydown1():
    # [...]

def Keydown2():
    # [...]

eventhandler = {pygame.QUIT: [Exit], pygame.KEYDOWN: [Keydown1, Keydown2]}
代码语言:javascript
复制
while True:
    for event in pygame.event.get():
        if event.type in eventhandler:
            for target in eventhandler[event.type]:
                target(event)

示例:

代码语言:javascript
复制
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的答案):

代码语言:javascript
复制
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)
票数 2
EN

Stack Overflow用户

发布于 2020-02-26 07:45:59

您不需要使用带有静态方法的类,并且要在Rabbid76 76的答案的基础上构建,一种(imho)优雅的方法是使用一个装饰器在dict中注册每个事件处理程序:

代码语言:javascript
复制
import pygame

event_handler_registry = {}


def register_event_handler(event):
    def decorator(fn):
        event_handler_registry[event] = fn
        return fn

    return decorator


@register_event_handler(pygame.QUIT)
def on_exit(event):
    pygame.quit()
    quit(0)


@register_event_handler(pygame.KEYDOWN)
def on_key_down(event):
    print(event.key)


while True:
    for event in pygame.event.get():
        event_handler = event_handler_registry.get(event.type)
        if event_handler:
            event_handler(event)
        else:
            print(f"No event handler for {event}")
票数 2
EN

Stack Overflow用户

发布于 2021-08-22 00:57:36

也许您可以在字符串中使用eval():

代码语言:javascript
复制
EVENTS = {
pygame.QUIT : "quit_handler()" ,
pygame.MOUSEBUTTONDOWN: "click_handler(event)"
}

for event in pygame.event.get:
    eval (EVENTS.get(event.type))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60406647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档