自学Python第十二天- 一些有用的模块:pygame (二)
在实现了动画后,就要让程序根据用户的行为进行互动了,即监听用户事件。然后根据各种事件及元素的行为进行相应的处理。
动态监听用户事件
之前列子中英雄飞机是自动飞行的,但是实际上应该让用户控制英雄飞机。这就需要监听用户的行为。pygame 提供了l两种方法来监测用户互动:监听事件和检查键盘状态。
监听事件
使用 pygame.event.get 方法来获取程序运行中的各种用户事件。该方法返回了一个事件列表,我们可以通过检测列表中的事件来进行相应处理。例如监听按键事件:
def __event_handler(self):
"""监听事件"""
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
print('右移动')
但是实际使用中判断用户是否按了键盘通常使用检查键盘状态的方式。因为在事件监听中,按下键盘触发一次事件,直到抬起键盘并再次按下,并不重复触发事件。所以当按住按键不松时,对于事件监听来说只触发了一次事件。这样灵活性大打折扣,且对于之后的行为处理会造成麻烦甚至是冲突。
通常监听事件用于两种事件:程序事件和自定义事件。
程序事件
程序事件指一些程序触发的事件,其实键盘按键事件也应该算程序事件,还有鼠标事件等。这里以一个飞机大战游戏中会用到的事件举例:关闭程序。
在程序运行过程中,点击右上角X按钮并不能关闭窗口,是因为我们没有写关闭程序的相关代码。当监听到关闭程序事件,则执行关闭程序的代码。
def __event_handler(self):
"""监听事件"""
for event in pygame.event.get():
# 判断用户是否点击了关闭按钮
if event.type == pygame.QUIT:
PlaneGame.__game__over() # 调用静态方法
@staticmethod # 定义为静态方法
def __game__over():
"""结束游戏"""
print('游戏结束')
pygame.quit() # 卸载 pygame 模块
exit() # 退出程序
自定义事件
除了程序事件外,我们可以自定义事件。pygame 的各种事件种类其实是一个整数,而 pygame 也定义了一个起始整数作为自定义事件,这个起始数使用 pygame.USEREVENT 来标记。所以每增加一个自定义事件,则在此标记上加1即可。当监听事件列表中有了这个数值,即触发了这个自定义事件。
在实际使用过程中,最经常用的就是通过计时器来触发事件。使用 pygame.time.set_time(event, millis)
来定时触发事件,event 是自定义的事件,millis 是间隔事件,单位毫秒。例:
CREATE_ENEMY_EVENT = pygame.USEREVENT # 创建自定义事件:创建敌机
# 设置定时器事件 - 创建敌机 1s
pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
即可以在监听方法中进行相应处理
def __event_handler(self):
"""监听事件"""
for event in pygame.event.get():
# 判断用户是否点击了关闭按钮
if event.type == pygame.QUIT:
PlaneGame.__game__over() # 调用静态方法
# 创建敌机
elif event.type == CREATE_ENEMY_EVENT:
enemy1 = Enemy1(self.image_all) # 创建敌机
self.enemy_group.add(enemy1) # 敌机精灵添加到敌机精灵组
检查键盘状态 (键盘按键行为)
pygame 使用 pygame.key.get_pressed 方法获取按键元组,通过键盘常量来判断元组中某一个键是否被按下:如果按下则对应数值为1。例:
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_RIGHT]:
print('右移动')
这样就可以通过判断按键是否按下来控制英雄飞机的行为:
def __event_handler(self):
"""监听事件"""
for event in pygame.event.get():
# 判断用户是否点击了关闭按钮
if event.type == pygame.QUIT:
PlaneGame.__game__over() # 调用静态方法
# 创建敌机
elif event.type == CREATE_ENEMY_EVENT:
enemy1 = Enemy1(self.image_all) # 创建敌机
self.enemy_group.add(enemy1) # 敌机精灵添加到敌机精灵组
# 使用键盘模块获取键盘按键 - 按键元组
keys_pressed = pygame.key.get_pressed()
# 判断元组中对应的按键索引值是否为1
if keys_pressed[pygame.K_RIGHT] or keys_pressed[pygame.K_d]:
self.hero.speed = [1, 0]
elif keys_pressed[pygame.K_LEFT] or keys_pressed[pygame.K_a]:
self.hero.speed = [-1, 0]
else:
self.hero.speed = [0, 0]
if keys_pressed[pygame.K_ESCAPE]:
PlaneGame.__game__over() # 调用静态方法
对元素行为进行处理
在游戏中,除了要对事件进行处理,还要对元素自身行为及相互行为进行处理。
元素的自身行为
元素自身行为是元素对象本身由于一定的条件产生的行为,例如最常见到的就是根据时间改变自身的图像,使自身形成动画效果。可以使用 pygame.time.get_ticks()
方法获得一个时间戳,并根据获得的时间戳和现在的时间对比判断时间间隔,来处理行为。这种行为一般写在自己的精灵类中。例如:
class Hero(GameSprite):
"""英雄精灵"""
def __init__(self, image_all):
# 通过图形资源获取背景图片对象
self.image = image_all.subsurface((1139, 517, 100, 124))
super().__init__(self.image, [0, 0]) # 设置英雄飞机图像及初始速度
# 英雄精灵初始位置
self.rect.bottom = SCREEN_RECT.height - 70
self.rect.centerx = SCREEN_RECT.centerx