读取事件

事件是驱动游戏进行和分支的重要部分,没有事件的存在,游戏只会在原地踏步并且不能响应任何玩家的操作,甚至连退出游戏都十分困难。事件不仅会来自于用户,也可能会来自系统,事件随时可能发生,并且量级巨大。pygame支持用户的各种操作,包括键盘、鼠标还有游戏手柄等,并且使用队列来处理这些巨大量级的事件。

在实际开发中,常常用pygame.event.get()这个生成器来读取队列中的事件。pygame.event.get()通常不会阻塞游戏的主循环,而pygame.event.wait()就不一样了,它会让整个程序停下来等待下一个事件的发生。

事件通常可以使用event.type属性来判断这个事件的类型,通过区分不同的事件类型,我们可以在程序中做出响应的处理。pygame中常用的事件类型有以下这些。

事件类型产生途径可用成员
QUIT用户按下窗口关闭按钮或者执行退出
ACTIVEEVENTpygame窗口获得焦点或者失去焦点gainstate
KEYDOWN键盘被按下unicodekeymod
KEYUP键盘被放开keymod
MOUSEMOTION鼠标移动posrelbuttons
MOUSEBUTTONDOWN鼠标按键按下posbutton
MOUSEBUTTONUP鼠标按键抬起posbutton
JOYAXISMOTION手柄移动joyaxisvalue
JOYBALLMOTION手柄控制球移动joyaxisvalue
JOYHATMOTION手柄数位杆移动joyaxisvalue
JOYBUTTONDOWN手柄按键按下joybutton
JOYBUTTONUP手柄按键抬起joybutton
VIDEORESIZE窗口缩放sizewh
VIDEOEXPOSE窗口显示
USEREVENT用户自定义事件

键盘事件

键盘事件比较简单,只是对按下的按键进行记录,不同的成员用来记录不同类型的按键。key用来记录按下或者释放的键值,由于键值是一个整型数字,并不方便使用,所以pygame在pygame.locals中提供了一系列的常量来供使用,其中按键采用K_xxx来表示,例如K_a表示按下了字母A键,空格和回车分别是K_SPACEK_RETURN

mod用来记录组合键信息,组合键通常使用位运算来判断,例如event.mod & pygame.locals.KMOD_CTRL如果为真,则表示用户按下了Ctrl键。常用的其他按键还有KMOD_SHIFTKMOD_ALT

pygame.key模块中,还提供了一个.get_pressed()函数,可以获得当前所有已经按下的键盘的值。这个函数会返回一个元组,元素的索引是键值,值为是否按下。所以对已经按下的键的判断还可以使用以下方式来完成。

pressed_keys = pygame.key.get_pressed()
if pressed_keys[K_SPACE]:
	# 处理空格键按下的逻辑
	pass

同样,获取组合键信息的函数是.get_mods()

处理鼠标事件

MOUSEMOTION事件在鼠标动作时产生,会在产生的事件中提供三个成员,其中buttons成员是一个元组,其中有三个整型值,分别代表左、中、右三个键,哪个值为1,就代表对应的哪个键被按下了。pos成员表示目前鼠标的位置。rel成员表示当前事件与上次事件发生时的鼠标位置距离。

MOUSEBUTTONDOWNMOUSEBUTTONUP两个事件只在鼠标按键点击和释放的时候产生,其中button成员代表哪个按键被操作,pos依旧代表发生事件时的鼠标位置。

阻止事件和自定义事件

通常不是所有的事件都是程序感兴趣的,但是pygame将其排入了队列,即便是不予理睬也会稍微的影响性能。这时可以使用pygame.event.set_blocked([事件类型名称])来对事件进行过滤,所有列在列表中的事件类型,pygame都会不再捕获。相反,使用pygame.event.set_allowed()可以用来设置允许的事件。

Pygame也支持自定义事件,为了使用自定义事件,需要先创建一个事件,再将其发送到pygame的事件队列中。这里的自定义事件并不仅是前表中的USEREVENT,也可以是自定义事件类型,或者是按键、鼠标等事件类型。例如可以使用以下示例来发送键盘事件和自定义事件。

# 创建键盘事件
key_event = pygame.event.Event(KEYDOWN, key=K_SPACE, mod=0, unicode=u' ')
pygame.event.post(key_event)

# 使用字典创建键盘事件
key_event = pygame.event.Event(KEYDOWN, {'key': K_SPACE, 'mod': 0, 'unicode': u' '})

# 创建自定义事件
ANEWUSEREVENT = USEREVENT + 1
custom_event = pygame.event.Event(ANEWUSEREVENT, message='Hello from custom event')
pygame.event.post(custom_event)