一、Game类中应该包含出现在场景上的所有精灵或其列表,例如本程序中的player、rocks、explosions等。如果后续要添加其他精灵,例如敌机,那么也要在Game类的构造方法中添加敌机列表,并在创建敌机时加入这一列表。创建精灵列表的方法是pygame.sprite.Group(),用这一方法创建的列表可以由pygame方便地更新和删除列表中的精灵。
二、Game类的主事件循环(run方法)几乎可以作为所有pygame游戏程序的固定写法。前文代码没有提供游戏暂停的功能,实际上添加游戏暂停的功能是非常简单的事,我们只需要通过三步就可以完成:
1、在Game类的构造方法中添加一个暂停标志:
self.pause = False
2、在主事件循环(run方法)更新游戏场景之前先判断是否处于暂停状态,即前文代码中第72行修改为:
if self.running and not self.pause:
3、在事件处理方法(__handle_event方法)中添加处理暂停标志切换的代码,例如按p键实现暂停和暂停恢复的功能,那么__handle_event方法中增加对按P键的处理:
# 83行以上省略
if event.type == pygame.QUIT or key_pressed[pygame.K_ESCAPE]:
self.running = False
elif key_pressed[pygame.K_p]:
# 暂停或从暂停中恢复游戏
self.pause = not self.pause
# 87行以下省略
重要补充说明:最新版本的pygame再用上面这种对按键事件的处理方式,已经无法正确运行。因此,Game类的__handle_event函数应改成下面这种形式,这样在老版本的pygame中也能正确运行:
def __handle_event(self):
for event in pygame.event.get():
# 按下窗体上的关闭按钮则停止主事件循环
if event.type == pygame.QUIT:
self.running = False
elif event.type == pygame.KEYDOWN:
# 按下p键则暂停或重新启动游戏
if event.key == pygame.K_p:
self.pause = not self.pause
# 按下ESC键则停止主事件循环
elif event.key == pygame.K_ESCAPE:
self.running = False
# 由于射击和移动等事件是由Player类处理的,还需要将事件传递给player处理
self.player.handle_event(event)
当然,如果更仔细,我们应该在开始页面(show_start_page函数)中再添加一行提示:
draw_text(screen, 'P键暂停或从暂停中恢复游戏', font_zh, 36, 'yellow',
pos_y=(pos_y + 30 + line_height * 4))
三、前文代码中玩家飞机所发射的子弹没有在Game类中管理。其实也可以放在Game类中管理,就像Rock和Explosion对象那样。只是子弹既然是玩家飞机所发射的,个人感觉由玩家飞机来管理更自然。毕竟player.shoot比game.shoot从语义上来看更合理。
(未完待续)