在上篇文章中,我们通过game_active标志来控制游戏的进行与停止。我们需要在点击“play”按钮后游戏才开始运行。因此将game_active = False。游戏在开始时处于非活动状态,等待点击play后运行。
def __init__(self, ai_settings): """初始化统计信息""" self.ai_settings = ai_settings self.reset_stats() # 让游戏一开始处于非活动状态 self.game_active = Falsepygame中没有内置创建按钮的方法,故我们采取最原始的方法绘制一个带标签的矩形。 button,py
import pygame.font class Button(): def __init__(self, ai_settings, screen, msg): """初始化按钮的属性""" self.screen = screen self.screen_rect = screen.get_rect() #设置按钮的尺寸和其他属性 self.width, self.height = 200, 50 self.button_color = (0, 255, 0) self.text_color = (255, 255, 255) self.font = pygame.font.SysFont(None, 48) #创建按钮的rect对象,居中 self.rect = pygame.Rect(0,0,self.width,self.height) self.rect.center = self.screen_rect.center #按钮的标签只需创建一次 self.prep_msg(msg)pygame.font的作用是将文本渲染到屏幕上,msg是显示按钮里的文本。
def prep_msg(self, msg): """将msg渲染为图像,并使其在按钮上居中""" self.msg_image = self.font.render(msg,True,self.text_color, self.button_color) self.msg_image_rect = self.msg_image.get_rect() self.msg_image_rect.center = self.rect.centerprep_msg()将参数和文字渲染为msg,调用font.render()把msg中的文本转换为图像,存储在msg_image中,让文本图像在按钮上居中。
def draw_button(self): #绘制一个用颜色填充的按钮,再绘制文本 self.screen.fill(self.button_color,self.rect) self.screen.blit(self.msg_image,self.msg_image_rect)draw_button()将按钮显示到屏幕上。 最后再alien_invasion.py中引入Button类,创建Play按钮,在gf.update_screen()中添加play_button实参,就可以在屏幕上显示button按钮了。
#创建play按钮 play_button = Button(ai_settings, screen, "Play") """游戏主循环""" while True: """监视键鼠事件""" gf.check_events(ai_settings, screen, ship, bullets) if stats.game_active: ship.update() #print(len(bullets)) gf.update_bullets(ai_settings, screen, ship, aliens, bullets) gf.update_aliens(ai_settings, stats, screen, ship, aliens, bullets) gf.update_screen(ai_settings, screen, stats, ship, aliens, bullets, play_button)修改update_screen(),如果game_active为false,就绘制play按钮。
def update_screen(ai_settings, screen, stats, ship, aliens, bullets, play_button): """更新屏幕上的图像,并切换到新屏幕""" --snip-- # 如果游戏处于非活动状态,就绘制Play按钮 if not stats.game_active: play_button.draw_button() # 让最近绘制的屏幕可见 pygame.display.flip()运行效果如下:
修改check_events()的定义,在其中添加了形参stats和play_button。使用stats来访问标志game_active,并使用play_button来检查玩家是否单击了Play按钮。 通过pygame.mouse.get_pos()来获得鼠标单击时的xy坐标,判断该坐标是否处于“play”按钮的rect坐标,如果处于就认为单击了按钮,game_active = True,游戏开始。
def check_events(ai_settings, screen, stats, play_button, ship, bullets): #键鼠响应 for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == pygame.KEYDOWN: check_keydown_events(event, ai_settings, screen, ship, bullets) elif event.type == pygame.KEYUP: check_keyup_events(event, ship) elif event.type == pygame.MOUSEBUTTONDOWN: mouse_x, mouse_y = pygame.mouse.get_pos() check_play_button(stats, play_button, mouse_x, mouse_y)在alien_invasion.py中调用check_events(),需要传递另外两个实参——stats和play_button
while True: """监视键鼠事件""" gf.check_events(ai_settings, screen, stats, play_button, ship, bullets)在1.3中我们添加了单击按钮开始游戏,但是没有处理游戏结束的情况。在玩家每次点击play按钮时都重置游戏,我们在check_play_button()中重置统计信息、删除现有的外星人和子弹、创建一群新的外星人,并让飞船居中。
def check_play_button(ai_settings, screen, stats, play_button, ship, aliens, bullets, mouse_x, mouse_y): """单击按钮时开始新游戏""" if play_button.rect.collidepoint(mouse_x, mouse_y): #重置游戏统计信息 stats.reset_stats() stats.game_active = True #清空外星人列表和子弹列表 aliens.empty() bullets.empty() #创建一群新的外星人 create_fleet(ai_settings,screen,ship,aliens) ship.center_ship()再修改check_events()和check_play_button()的形参。
def check_events(ai_settings, screen, stats, play_button, ship, aliens,bullets): #键鼠响应 for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == pygame.KEYDOWN: check_keydown_events(event, ai_settings, screen, ship, bullets) elif event.type == pygame.KEYUP: check_keyup_events(event, ship) elif event.type == pygame.MOUSEBUTTONDOWN: mouse_x, mouse_y = pygame.mouse.get_pos() check_play_button(ai_settings, screen, stats, play_button, ship,aliens, bullets, mouse_x, mouse_y)alien_invasion.py
"""监视键鼠事件""" gf.check_events(ai_settings, screen, stats, play_button, ship,aliens, bullets)在游戏运行时,即便按钮不可见,但只要鼠标单击原来按钮所在的游戏时还是会做出响应。因此我们将响应条件改为在game_active=False时才开始。同理光标得修改也如此。
def check_play_button(ai_settings, screen, stats, play_button, ship, aliens, bullets, mouse_x, mouse_y): """单击按钮时开始新游戏""" button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y) if button_clicked and not stats.game_active: #隐藏光标 pygame.mouse.set_visible(False) #重置游戏统计信息 stats.reset_stats() stats.game_active = True #清空外星人列表和子弹列表 aliens.empty() bullets.empty() #创建一群新的外星人 create_fleet(ai_settings,screen,ship,aliens) ship.center_ship()在游戏结束后,我们需要重新显示光标,能够点击按钮,故将ship_hit()函数修改如下:
def ship_hit(ai_settings, stats, screen, ship, aliens, bullets): """响应被外星人撞到的飞船""" if stats.ships_left > 0: #将ships_left减1 stats.ships_left -= 1 #清空外星人列表和子弹列表 aliens.empty() bullets.empty() #创建新的外星人 create_fleet(ai_settings, screen, ship, aliens) ship.center_ship() #暂停 sleep(0.5) else: stats.game_active = False pygame.mouse.set_visible(True)