0

我正在使用 Pygame 组合一个组件实体游戏引擎,并且我正在使用自定义 Pygame Userevents 作为我的消息传递系统(引擎中不同子系统可以在不真正了解彼此的情况下进行通信的方式)。

消息传递系统通过将事件类型列表附加到系统来工作。在 Engine 类(管理系统)的每个更新周期中,将该系统的事件过滤列表传递给系统,以便它可以对这些事件采取行动。

我有一个组件工厂,它创建组件对象,将对对象的引用附加到事件,然后发布事件。在我正在测试的有问题的代码中,我ADDINPUTCOMPONENT在创建InputComponent对象后发布了一个事件(自定义 Pygame Userevent)。

在我的测试代码中,您可以看到我创建了一个输入系统,将其安装在具有正确事件类型的引擎上,然后创建一个输入组件,它应该触发事件。

我已验证发布事件的代码正在发生。我还验证了引擎将事件正确绑定到输入系统。

您可以在我的更新函数中看到InputSystem,我应该处理从工厂发布的事件,但是我从未在 .返回的事件列表中看到该事件pygame.event.get()

引擎

class PygameEngine(object):
    def __init__(self, systems=None):
        self.systems = list() if systems is None else systems

    def install_system(self, system, event_types=None):
        new_system = SystemEntity(system, event_types)
        self.systems.append(new_system)

    def update(self, time, events):
        for i in self.systems:
            i.system.update(time, 
                filter(lambda x: x.type in i.event_types, events))

系统

class InputSystem(object):

    def __init__(self, components=None):
        # a map of lists, map keys are input devices, list items are
        #   components mapped to that device
        self.components = defaultdict(list) if components is None else components

    def update(self, time, events=None):

        for device, components in self.components.items():
            for comp in components:
                comp.last_state = copy.deepcopy(comp.state)
                print comp.state

        for event in events:

            # system events
            if event.type == ADDINPUTCOMPONENT:
                self.components[event.device].append(event.component)
                print "Added new input component"
            elif event.type == REMOVEINPUTCOMPONENT:
                self.components[event.device].remove(event.component)
            elif event.type == UPDATEBINDINGS:
                pass

工厂

def create_component(self, type, **props):
        component = None

        # InputComponent
        if type == 'input':
            device = props['device']
            entity_id = props['entity_id']
            # TODO: convert bindings to a bidict
            bindings = dict() if not 'bindings' in props else props['bindings']
            component = inputs.InputComponent(entity_id, bindings)
            new_event = event.Event(ADDINPUTCOMPONENT, device=device, component=component)
            event.post(new_event)

测试代码

inp = inputs.InputSystem()
eng.install_system(inp, (ADDINPUTCOMPONENT, REMOVEINPUTCOMPONENT,
                         UPDATEBINDINGS, pygame.KEYDOWN,
                         pygame.KEYUP, pygame.JOYBUTTONDOWN,
                         pygame.JOYBUTTONUP, pygame.MOUSEBUTTONDOWN,
                         pygame.MOUSEBUTTONUP))
t_entity = factory.create_entity()
t_bindings = {
    'up': pygame.K_UP,
    'down': pygame.K_DOWN,
    'left': pygame.K_LEFT,
    'right': pygame.K_RIGHT
}
t_inp_component = factory.create_component('input', device=-1,
                                           entity_id=t_entity.entity_id,
                                           bindings=t_bindings)

游戏循环

while not(done):
    last_time = current_time
    current_time = pygame.time.get_ticks()
    time_since_last_update = current_time - last_time
    events = pygame.event.get()

    eng.update(time_since_last_update, events)
4

1 回答 1

3

好吧,我发现了我的问题所在。从文档中pygame.event

所有事件都有一个类型标识符。此事件类型介于 NOEVENT 和 NUMEVENTS 的值之间。所有用户定义的事件都可以具有 USEREVENT 或更高的值。建议确保您的活动 ID 遵循此系统。

http://www.pygame.org/docs/ref/event.html

NOEVENTNUMEVENTS是值 0、32和24的“常量”。USEREVENT发布类型值为 32 或更大的事件会导致 pygame 基本上放弃该事件,它会出现。这意味着您只有 8 个可能的自定义事件值 ( NUMEVENTS- USEREVENT)。

我没有看到发布的事件是 39。它的定义如下:

ADDINPUTCOMPONENT = USEREVENT + 15

我尝试将其更改为USEREVENT + 1并且有效。

本质上,如果您想拥有超过 8 种类型的自定义事件,您只需向您发布的事件添加一个属性,以便区分事件类型。

此外,此限制似乎是从 SDL 继承的: http ://www.libsdl.org/docs/html/sdluserevent.html

于 2013-08-08T18:31:17.117 回答