接着上节的继续学习,在本章中,我们将结束游戏《外星人入侵》的开发。我们将添加一个 Play 按钮,用于根据需要启动游戏以及在游戏结束后重启游戏。我们还将修改这个游戏,使其在玩家的等级提高时加快节奏,并实现一个记分系统。
由于 Pygame 没有内置创建按钮的方法,我们创建一个 Button 类,用于创建带标签的实心矩形。你可以在游戏中使用这些代码来创建任何按钮。下面是 Button 类的第一部分,请将这个类保存为 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)
- 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.center
- def draw_button(self):
- #绘制一个用颜色填充的按钮,再绘制文本
- self.screen.fill(self.button_color,self.rect)
- self.screen.blit(self.msg_image,self.msg_image_rect)
代码中已经注释的很清楚了,不再做过多的介绍,这里重点说一下几个点:
(1)导入了模块 pygame.font,它让 Pygame 能够将文本渲染到屏幕上。
(2)pygame.font.SysFont(None,48) 指定使用什么字体来渲染文本。实参 None 让 Pygame 使用默认字体,而 48 指定了文本的字号。
(3)方法 prep_msg() 接受实参 self 以及要渲染为图像的文本(msg)。调用 font.render() 将存储在 msg 中的文本转换为图像,然后将该图像存储在 msg_image 中。
(4)方法 font.render() 还接受一个布尔实参,该实参指定开启还是关闭反锯齿功能(反锯齿让文本的边缘更平滑)
(5)screen.fill() 来绘制表示按钮的矩形,再调用 screen.blit(),并向它传递一幅图像以及与该图像相关联的 rect 对象,从而在屏幕上绘制文本图像。
在 alien_invasion.py 中添加标亮的代码:
- import pygame
- from pygame.sprite import Group
- from settings import Settings
- from game_stats import GameStats
- from ship import Ship
- import game_functions as gf
- from button import Button
- def run_game():
- # Initialize pygame, settings, and screen object.
- pygame.init()
- ai_settings = Settings()
- screen = pygame.display.set_mode(
- (ai_settings.screen_width, ai_settings.screen_height))
- pygame.display.set_caption("Alien Invasion")
- #创建play按钮
- play_button = Button(ai_settings,screen,"Play")
- # Create an instance to store game statistics.
- stats = GameStats(ai_settings)
- # Set the background color.
- bg_color = (230, 230, 230)
- # Make a ship, a group of bullets, and a group of aliens.
- ship = Ship(ai_settings, screen)
- bullets = Group()
- aliens = Group()
- # Create the fleet of aliens.
- gf.create_fleet(ai_settings, screen, ship, aliens)
- # Start the main loop for the game.
- while True:
- gf.check_events(ai_settings, screen, ship, bullets)
- if stats.game_active:
- ship.update()
- 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)
- run_game()
修改 update_screen(),以便在游戏处于非活动状态时显示 Play 按钮:
- def update_screen(ai_settings, screen,stats, ship, aliens, bullets,play_button):
- """Update images on the screen, and flip to the new screen."""
- # Redraw the screen, each pass through the loop.
- screen.fill(ai_settings.bg_color)
- # Redraw all bullets, behind ship and aliens.
- for bullet in bullets.sprites():
- bullet.draw_bullet()
- ship.blitme()
- aliens.draw(screen)
- if not stats.game_active :
- play_button.draw_button()
- # Make the most recently drawn screen visible.
- pygame.display.flip()
运行效果如下:
为在玩家单击 Play 按钮时开始新游戏,需在 game_functions.py 中添加如下代码,以监视与这个按钮相关的鼠标事件:
- def check_events(ai_settings, screen, stats,play_button,ship, bullets):
- """Respond to keypresses and mouse events."""
- 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)
- def check_play_button(stats,play_button,mouse_x,mouse_y) :
- #在玩家点击play按钮时开始游戏
- if play_button.rect.collidepoint(mouse_x,mouse_y) :
- stats.game_active = True
注意一下几点:
(1)无论玩家单击屏幕的什么地方,Pygame 都将检测到一个 MOUSEBUTTONDOWN 事件,但我们只关心这个游戏在玩家用鼠标单击 Play 按钮时作出响应。
(2)使用了 pygame.mouse.get_pos(),它返回一个元组,其中包含玩家单击时鼠标的 x 和 y 坐标。
(3)使用 collidepoint() 检查鼠标单击位置是否在 Play 按钮的 rect 内,如果是这样的,我们就将 game_active 设置为 True,让游戏就此开始!
四 重置游戏,将按钮切换到非活动状态以及隐藏光标
前面编写的代码只处理了玩家第一次单击 Play 按钮的情况,而没有处理游戏结束的情况,因为没有重置导致游戏结束的条件。为在玩家每次单击 Play 按钮时都重置游戏,需要重置统计信息、删除现有的外星人和子弹、创建一群新的外星人,并让飞船居中。
- def check_events(ai_settings, screen, stats,play_button,ship,aliens, bullets):
- """Respond to keypresses and mouse events."""
- 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)
- def check_play_button(ai_settings,screen,stats,play_button,ship,aliens,bullets,mouse_x,mouse_y) :
- #在玩家点击play按钮时开始游戏
- 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()
注意一下几点:
(1),Play 按钮存在一个问题,那就是即便 Play 按钮不可见,玩家单击其原来所在的区域时,游戏依然会作出响应。游戏开始后,如果玩家不小心单击了 Play 按钮原来所处的区域,游戏将重新开始!为修复这个问题,可让游戏仅在 game_active 为 False 时才开始!
- button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
- if button_clicked and not stats.game_active:
(2)为让玩家能够开始游戏,我们要让光标可见,但游戏开始后,光标只会添乱。在游戏处于活动状态时让光标不可见,游戏结束后,我们将重新显示光标,让玩家能够单击 Play 按钮来开始新游戏。
- def check_play_button(ai_settings, screen, stats, play_button, ship, aliens,bullets, mouse_x, mouse_y):
- """在玩家单击Play按钮时开始新游戏"""
- button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
- if button_clicked and not stats.game_active:
- # 隐藏光标
- pygame.mouse.set_visible(False)
还有好多要写,但实在写不下去了,明天再写吧!休息休息!
来源: https://www.cnblogs.com/majianchao/p/8126356.html