Pygame - 如何创建更多USEREVENT类型的事件?

3 投票
3 回答
8571 浏览
提问于 2025-04-18 06:02

这个问题是因为我需要创建很多USEREVENT类型的事件。由于找不到关于如何创建超过限制的userevent的信息,所以我来这里寻求帮助。

目前我知道USEREVENT类型的事件值是24,允许的最大ID是31。我还发现一些ID是保留的,至少在官方文档的一个评论中提到过(http://www.pygame.org/docs/ref/event.html#comment_pygame_event_Event)。

基于这些信息,我有两个问题:那些SDL_EVENT_RESERVED的事件ID可以安全地用作用户创建事件的额外空间吗(比如一个定时器:pygame.time.set_timer(USEREVENT + 7, 1000))?有没有办法像定时器代码示例那样创建无限数量的用户自定义事件?

如果我的问题因为措辞不当或其他原因而让人难以理解,我很抱歉。

3 个回答

0

pygame.time.set_timer() 这个函数可以在事件队列中不断创建一个 USEREVENT。时间需要以毫秒为单位设置。例如:

time_interval = 500 # 500 milliseconds == 0.1 seconds
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, time_interval)

需要注意的是,在pygame中可以定义自定义事件。每个事件都需要一个独特的ID。用户事件的ID必须在 pygame.USEREVENT(24)和 pygame.NUMEVENTS(32)之间。在这种情况下,pygame.USEREVENT+1 就是定时事件的ID。

自从Pygame 2.0版本开始,可以使用 pygame.event.custom_type() 来代替 pygame.USEREVENT+1pygame.event.custom_type() 的作用是:

为自定义用途保留一个 pygame.USEREVENT。如果创建的事件太多,会引发一个 pygame.errorstandard 的异常。

例如:

timer_event = pygame.event.custom_type()
pygame.time.set_timer(timer_event, 500)
1

如果我是你,我会只用一种 USEREVENT 类型,来创建我想要的多个自定义事件。实现这个的方式就是给事件的名称或类型加一个特别的属性。下面有个小例子可以让你更清楚...

这个是在 Windows 10 上,使用 pygame 1.9.6 和 Python 3.7.3 测试的。

import pygame as pg

ON_MY_MOUSE_CLICK = 1  # your own codes for your own events...
ON_MY_SCROLL = 2
BLAH_BLAH = 3
# etc ...

pg.init()

video = pg.display.set_mode((100,100))

MouseEvent = pg.event.Event(pg.USEREVENT, MyOwnType=ON_MY_MOUSE_CLICK )
ScrollEvent = pg.event.Event(pg.USEREVENT, MyOwnType=ON_MY_SCROLL)
blahblahEvent = pg.event.Event(pg.USEREVENT, MyOwnType=BLAH_BLAH)

pg.event.post(MouseEvent)  # call your own type
pg.event.post(ScrollEvent)  # call your own type

for event in pg.event.get():
    if (event.type == pg.QUIT):
        pass  # your built-in event handle goes here

    elif (event.type == pg.USEREVENT):  # here we go
        if (event.MyOwnType == ON_MY_MOUSE_CLICK):
            print("My own mouse event!")  # handle for your own event

        elif (event.MyOwnType == ON_MY_SCROLL):
            print("My own scroll event!")  # handle for your own event

        elif (event.MyOwnType == BLAH_BLAH):
            print("My own blah blah event!")  # handle for your own event

编辑:

如果你发现自己需要使用 pg.time.set_timer,我知道我们不能把 MyOwnType 直接赋值给 set_timer。不过,你可以随意使用我在 GitHub 上的 set_interval.py。它是 MIT 许可证的,所以你不用担心一般的 GNU 许可证之类的问题...

这里有个例子:

from set_interval import setInterval
import pygame as pg

def set_timer(eventObj, interval):
    func = lambda x: pg.event.post(x)
    return setInterval(func=func, sec=interval, args=[eventObj])

ON_MY_MOUSE_CLICK = 1  # your own codes for your own events...
ON_MY_SCROLL = 2
BLAH_BLAH = 3
# etc ...

pg.init()

video = pg.display.set_mode((100,100))

MouseEvent = pg.event.Event(pg.USEREVENT, MyOwnType=ON_MY_MOUSE_CLICK )
ScrollEvent = pg.event.Event(pg.USEREVENT, MyOwnType=ON_MY_SCROLL)
blahblahEvent = pg.event.Event(pg.USEREVENT, MyOwnType=BLAH_BLAH)

# replacement for pygame.time.set_timer(MouseEvent, 1000)
myIntervalHandle1 = set_timer(MouseEvent, 1)

# replacement for pygame.time.set_timer(ScrollEvent, 2500)
myIntervalHandle2 = set_timer(ScrollEvent, 2.5)

running = True
while running :
    for event in pg.event.get():
        if (event.type == pg.QUIT):
            pg.display.quit()
            myIntervalHandle1.stop()  # stop timer
            myIntervalHandle2.stop()  # stop timer
            running = False

        elif (event.type == pg.USEREVENT):  # here we go
            if (event.MyOwnType == ON_MY_MOUSE_CLICK):
                print("My own mouse event!")  # handle for your own event

            elif (event.MyOwnType == ON_MY_SCROLL):
                print("My own scroll event!")  # handle for your own event

            elif (event.MyOwnType == BLAH_BLAH):
                print("My own blah blah event!")  # handle for your own event

你可以在这里找到 set_interval.py

https://github.com/Hzzkygcs/setInterval-python

7

用户事件的范围应该在:

  • pygame.USEREVENT: 24
  • pygame.NUMEVENTS: 32

所以你可以有9种不同的用户事件。

通常的做法是定义一个常量:

SOME_EVENT = pygame.USEREVENT + 0
ANOTHER_EVENT = pygame.USEREVENT + 1
...

如果你用 event(...) 来创建事件,你可以给这个事件添加一些属性,这样你就可以创建很多不同的子事件,并给它们添加额外的数据,比如:键盘事件。

不过,当你使用 pygame.time.set_timer() 时,你只能使用一个ID,没法添加其他信息。

撰写回答