您现在的位置是:首页 >技术交流 >用python写游戏:《外星人入侵》给游戏添加记分功能网站首页技术交流

用python写游戏:《外星人入侵》给游戏添加记分功能

兔C 2023-06-10 00:00:02
简介用python写游戏:《外星人入侵》给游戏添加记分功能

项目需求:

在游戏《外星人入侵》中,玩家控制着一艘最初出现在屏幕底部中央的飞船。玩家可以使用箭头键左右移动飞船,还可使用空格键进行射击。游戏开始时,一群外星人出现在天空中,他们在屏幕中向下移动。玩家的任务是射杀这些外星人。玩家将所有外星人都消灭干净后,将出现一群新的外星人,他们移动的速度。只要有外星人撞到了玩家的飞船或到达了屏幕底部,玩家就损失一艘飞船。玩家损失三艘飞船后,游戏结束。


往期博客
关于: 设置飞船的博客

关于:给飞船添加射击功能的博客

关于:设置外星人群的博客

关于:添加游戏结束功能的博客


闲 谈

今天是 2023.4.11,星期二.
用 python 写《外星人入侵》游戏的最后一章内容。

我们每个喜欢编程的人都是持续学习的人,每个人的学习方式都不一样,学习本身没有方法可言。
只是方式不同,我的学习方式是读书,然后搬运到博客里。发出去,
自己一直觉得,这样就代表学过了,有不明白的地方,搬运过去就想通了。
有遗忘的点,自己随手可查,因为都是亲手搬运,所以知道答案在哪。。

在文章里,我可能废话较多,这是我的难言之隐。因为这样,我就觉得自己还在理想的地方。


记 分:

现在我们需要给游戏添加一个按钮,一个用于开始游戏的按钮。
然后还需要修改这个游戏,因为需要随着玩家等级的提高来提高游戏节奏速度。
最后是一个记分系统,记录玩家游戏时所得分数。

添加按钮

为什么要添加按钮?
我们现在游戏的状态是只要启动程序,外星人群不会等玩家做好准备就开始入侵。
所以我们要添加一个启动游戏的按钮,当程序启动时,玩家点击按钮后,外星人群才可以开始移动。

通过这点,我们可以分析添加按钮的需求应该是:

按钮出现在游戏开始前,并在游戏结束后重新出现,因为玩家游戏失败后,可再次点击按钮重新开始游戏。而不是从新启动应用。

如何添加按钮?
先让游戏处于非活动状态,然后提示玩家点击按钮后开始游戏。

game_stats.py:

将 game_sactive 状态改为 未激活状态

		self.game_active = False

现在即便程序启动,游戏也会处于非活动状态。

等我们创建按钮后,玩家才可以开始游戏。

由于python没有内置创建按钮的方法,所以我们需要自己去创建一个Button类,用于创建带标签的实心矩形,也就是我们要创建的 play按钮。

有了Button类 之后,我们可以在游戏的任何地方创建按钮。

button.py:

"""pygame.font 用于将本文渲染到屏幕上"""
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)
		
				#None 参数用于指定使用什么字体来进行渲染。
				#None为pygame默认字体,48为字体字号
		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)

在屏幕上绘制按钮

现在我们可以开始通过 Button类来创建按钮了。
这个游戏只需要一个按钮,所以我们直接在

alien_invasion.py 中创建:

from button import Button

	#创建按钮
	play_button = Button(ai_settings,screen,"Play")

	# while 循环来控制游戏
	while True:
		gf.update_screen(ai_settings,screen,stats,ship,aliens,bullets,play_button)

将 按钮变量传递给更新绘制屏幕的方法是为了希望在屏幕更新时显示按钮。

下面是对 update_screen 方法的更改:

def update_screen(ai_settings,screen,ship,aliens,bullets,play_button):
		#每次循环时都重绘屏幕
		screen.fill(ai_settings.bg_color)
		#在飞船和外星人后面重绘所有子弹
		for bullet in bullets.sprites():
			bullet.draw_bullet()
		ship.blitme()
		aliens.draw(screen)
		
		#如果游戏处于非活动状态,就绘制play按钮
		if not stats.game_active:
			play_button.draw_button()
		
		#让最近绘制的屏幕可见
		pygame.display.flip()

现在我们运行游戏,看一下按钮添加后的效果。

在这里插入图片描述

为了让玩家点击按钮开始游戏,我们需要添加监视该按钮的鼠标事件:

game_functions.py:

#管理被隔离的监听循环事件	
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)
			
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		

alien_invasion.py:

while True:
		gf.check_events(ai_settings,screen,stats,play_button,ship,bullets)

重置游戏

前面写的代码只处理了玩家第一次单击按钮的情况,而没有处理游戏结束的情况,
因为没有重置导致游戏结束的条件。

为了在玩家每次单击按钮时都重置游戏,需要重置统计信息,删除现有的外星人和子弹,创建一群新的外星人,并让飞船居中。

game_functions.py:

def check_play_button(ai_settings,screen,stats,play_button,ship,aliens,bullets,mouse_x,mouse_y):
	#在玩家单机play按钮时开始游戏
	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()	

继续修改调用处:
game_functions.py:

#管理被隔离的监听循环事件	
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)
			

aliens.invasion.py:

# while 循环来控制游戏
	while True:
		gf.check_events(ai_settings,screen,stats,play_button,ship,aliens,bullets)

将 play 按钮切换到非活动状态

当前的 play 按钮存在一个问题,那就是即便按钮不可见,用户点击按钮的位置游戏依然会做出响应。

为了修复这个问题,我们可以让游戏尽在 game_active为False时才开始:
game_functions.py

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)
	#在玩家单机play按钮时开始游戏
	if button_clicked and not stats.game_active:
		stats.reset_stats()
		stats.game_active = True
		
		#清空外星人列表和子弹列表
		aliens.empty()
		bullets.empty()
		
		#创建一群新的外星人
		create_fleet(ai_settings,screen,ship,aliens)
		ship.center_ship()			
			

隐藏光标

为让玩家在游戏时看不到光标。

game_functions.py:

def check_play_button(ai_settings,screen,stats,play_button,ship,aliens,bullets,mouse_x,mouse_y):

	if button_clicked and not stats.game_active:
		#隐藏光标
		pygame.mouse.set_visible(False)


def ship_hit(ai_settings,stats,screen,ship,aliens,bullets):
	else:
		stats.game_active = False
		pygame.mouse.set_visible(True)
提高等级

当前游戏里的外星人被玩家消灭后,玩家会提高一个等级,可游戏的难度并没有改变。
下面我们就着手去改动游戏的节奏。

修改速度设置

我们首先组织 aisettings类,
将游戏设置划分为静态和动态的两组。对于随着游戏进行而变化的设置,我们还确保它们在开始新游戏时被重置。

settings.py __ init __():

class Settings():
	#存储《外星人入侵》的所有设置的类
	
	def __init__(self):
		self.screen_width = 1200
		self.screen_height = 800
		self.bg_color = (230,230,230)
		
		self.bullet_speed_factor = 1
		self.bullet_width = 3
		self.bullet_height = 15
		self.bullet_color = 60,60,60
		self.bullets_allowed = 3
		#外星人设置
		self.fleet_drop_speed =10		
		#初始化岁游戏进行而变化的设置
		self.speedup_scale = 1.1
		self.initialize_dynamic_settings()
		
	def initialize_dynamic_settings(self):
		#飞船的设置
		self.ship_speed_factor = 1.5
		#飞船的生命值
		self.ship_limit = 3
		#外星人的设置
		self.alien_speed_factor = 1
		
		#fleet_direction为1表示向右移动,为-1表示向左移动
		self.fleet_direction =1
		
	def increase_speed(self):
		self.ship_speed_factor *= self.speedup_scale
		self.bullet_speed_factor *= self.speedup_scale
		self.alien_speed_factor *= self.speedup_scale
重置速度

我们刚才提高了游戏等级,但是没有重置速度,这样会导致什么问题呢?

玩家在第一次游戏时,游戏进度随着玩家操作的提升而提升,而当玩家失去所有飞船生命值重新开始游戏后,游戏的速度还是提升之后的速度,我们需要将速度重置一下,以便于在新游戏时,速度也是游戏开始时该有的初始速度。

game_functions.py:

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)
	#在玩家单机play按钮时开始游戏
	if button_clicked and not stats.game_active:
		#重置游戏设置
		ai_settings.initialize_dynamic_settings()
		
		#隐藏光标
		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()
记分

下面我们来给游戏添加一个记分系统,以实时跟踪玩家的得分,并显示最高得分、当前等级和余下的飞船数。

得分是游戏的一项统计信息。
在GameStats中添加一个 score属性:

	def reset_stats(self):
		#初始化在游戏运行期间可能变化的统计信息
		self.ships_left = self.ai_settings.ship_limit
		self.score =0

我们将记分的属性写在 reset_stats()方法中是因为在每次开始游戏时都重置得分。

显示得分

如果想让得分显示在游戏中,我们还需要创建一个新类:Scoreboard。
目前这个类,我们只让其显示玩家得分。之后在考虑添加显示最高得分,等级,飞船余下的生命数值。

scoreboard.py:

import pygame.font

class Scoreboard():
	#显示得分信息的类
	def __init__(self,ai_settings,screen,stats):
		#初始化现实得分涉及的属性
		self.screen = screen
		self.screen_rect = screen.get_rect()
		self.ai_settings = ai_settings
		self.stats = stats
		
		#显示得分信息时使用的字体设置
		self.text_color = (30,30,30)
		self.font = pygame.font.SysFont(None,48)
		
		#准备初始得分图像
		self.prep_score()

	def prep_score(self):
		#将得分转换为一副渲染的图像
		score_str = str(self.stats.score)
		self.score_image = self.font.render(score_str,True,self.text_color,self.ai_settings.bg_color)
		
		#将得分放到屏幕上
		self.score_rect = self.score_image.get_rect()
		self.score_rect.right = self.screen_rect.right - 20
		self.score_rect.top = 20
	
	def show_score(self):
		#在屏幕上显示得分
		self.screen.blit(self.score_image,self.score_rect)
创建记分牌

为显示得分,我们在 alien_invasion,py中创建一个Scoreboard 实例:

from scoreboard import Scoreboard


	#创建存储游戏统计信息的实例,并创建记分牌
	#创建一个用于存储游戏统计信息的实例
	stats = GameStats(ai_settings)
	# 记分牌
	sb = Scoreboard(ai_settings,screen,stats)

# while 循环来控制游戏
	while True:
		gf.update_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,play_button)

创建了记分牌的实例,又改动了 update_screen 的传递参数,所以在update_screen方法的定义处,我们也需要修改:

game_functions.py:

def update_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,play_button):
		#每次循环时都重绘屏幕
		screen.fill(ai_settings.bg_color)
		#在飞船和外星人后面重绘所有子弹
		for bullet in bullets.sprites():
			bullet.draw_bullet()
		ship.blitme()
		aliens.draw(screen)
		
		#显示得分
		sb.show_score()
		
		#如果游戏处于非活动状态,就绘制play按钮
		if not stats.game_active:
			play_button.draw_button()
		
		#让最近绘制的屏幕可见
		pygame.display.flip()

来开一下 记分牌的设置效果:
在这里插入图片描述

在外星人被消灭时显示得分

现在我们已经成功把记分牌设置到游戏中了,下一步要做的就是实时计算得分,
每当有外星人被击中时,我们都更新stats.score 的值,再调用 prep_score更新得分图像。

但是在此之前,我们需要指定玩家每击落一个外星人都将得到多少个点:

settings.py:

def initialize_dynamic_settings(self):
	#记分
	self.alien_points  = 50

随着游戏的进行,我们将提高每个外星人值的点数。

为了确保每次开始新游戏时这个值都会被重置:

game_functions.py:

def check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets):	
	#检查是否有子弹击中外星人,如果是,删除相应子弹和外星人。
	collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
	
	if len(aliens) ==0:
		bullets.empty()
		ai_settings.increase_speed()
		create_fleet(ai_settings,screen,ship,aliens)
	if collisions:
		stats.score +=ai_settings.alien_points
		sb.prep_score()

修改调用处:
game_functions.py:

def update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets):
	#更新子弹的位置,并删除已消失的子弹
	#更新子弹的位置
	bullets.update()
	
	#删除已消失的子弹
	for bullet in bullets.copy():
		if bullet.rect.bottom <= 0:
			bullets.remove(bullet)
			
	check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets)

alien_invasion.py:

	while True:
		gf.update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets)

现在可以测试一下记分功能了。

在这里插入图片描述

将消灭的每个外星人的点数都计入得分

目前,如果有在同一次循环里的两颗子弹射中了外星人,或是因为子弹过宽射中了多多个外星人,玩家都只能得到击杀了一个外星人的分数值,为修复这种问题,我们来调整检测子弹和外星人的碰撞方式。

在方法check_bullet_alien_collisions()中,与外星人碰撞的子弹都是字典 collisions中的一个键;而与每颗子弹相关的值都是一个列表,其中包含该子弹撞到的外星人。我们遍历字典 collisions,确保将消灭的每个外星人的点数都记入得分:

game_functions.py:

def check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets):	
	#检查是否有子弹击中外星人,如果是,删除相应子弹和外星人。
	collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
	
	if len(aliens) ==0:
		bullets.empty()
		ai_settings.increase_speed()
		create_fleet(ai_settings,screen,ship,aliens)
		
	if collisions:
		for aliens in collisions.values():
			stats.score += ai_settings.alien_points *len(aliens)
			sb.prep_score()
		stats.score +=ai_settings.alien_points
		sb.prep_score()
提高点数

在游戏中,玩家的等级会不对提高,游戏也会随之增加难度,因此处于较高的等级时,外星人的点数应更高。
settings.py:

	def __init__(self):
		#外星人点数的提高速度
		self.score_scale = 1.5
		
	def increase_speed(self):
		self.alien_points = int(self.alien_points * self.score_scale)
美化积分

在大多数街机风格游戏中,得分都显示为 10 的倍数,下面也让我们的得分系统遵循这个原则。

设置得分的格式,使用逗号表示千位分隔符。

scoreboard.py:

def prep_score(self):
		#将得分转换为一副渲染的图像
		score_str = str(self.stats.score)
		rounded_score = int(round(self.stats.score,-1))
		score_str = "{:,}".format(rounded_score)

为将得分进行美化,我们使用了 round 函数,该函数接收两个参数,它可以实现让小数精确到小数点后多少位。而实现小数位数也是由第二个参数实现的。如果将其置定为负数,该函数就会将其进行处理的参数圆整到 10、100、1000等整数倍。
round()总是返回一个小数值,所以我们使用int()让其转换为整数值。

现在我们来看一下游戏积分的美化效果:
在这里插入图片描述

给游戏设置高分记录

每个游戏都有类似最高得分的排行,现在我们来给《外星人入侵》添加一个最高分的榜单。

先将最高得分存储在 GameStats 中。
game_stats.py:

def __init__(self,ai_settings):
	self.high_score = 0

为了放置最高得分值进行重置,所以将其设置在 初始化方法当中。

设置好了存储最高得分的变量后,我们需要将其显示到屏幕当中,开始修改 scoreboard.py:

修改 __ init __()方法:

def __init__(self,ai_settings,screen,stats):
	self.prep_high_score()

#为将最高得分显示在屏幕上而定义的新方法
def prep_high_score(self):
		#将最高得分转换为渲染的图像
		high_score = int(round(self.stats.high_score,-1))
		high_score_str = "{:,}".format(high_score)
		
		self.high_score_image = self.font.render(high_score_str,True,self.text_color,self.ai_settings.bg_color)
		
		#将最高得分显示在屏幕顶部
		self.high_score_rect = self.high_score_image.get_rect()
		self.high_score_rect.centerx = self.screen_rect.centerx
		self.high_score_rect.top = self.score_rect.top

我们来运行游戏,来看一下最高得分设置效果:
在这里插入图片描述

接着,为了检查是否诞生了新的最高分,
在game_functions.py 中添加一个新函数checck_high_score():

def check_high_score(stats,sb):
	#检查是否诞生了新的最高分
	if stats.score > stats.high_score:
		stats.high_score = stats.score
		sb.prep_high_score()

函数 check_high_score() 包含两个参数:
stats 和 sb ,它使用 stats 来比较当前得分和最高得分。并在必要使用使用sb来修改最高得分图像。

在 函数 check_bulleet_alien_collisions()中,每当有外星人被消灭,
都需要在更新得分后调用 check_high_score():

def check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets):
	check_high_score(stats,sb)

现在我们来看一下设置最高分记录的效果:
在这里插入图片描述

显示等级

为了能够在游戏中显示玩家的等级,我们现在 GameStats中添加一个表示当前等级的属性。

def reset_stats(self):
	self.level = 1

为了在每次开始新游戏时初始化等级,我们将其定义在 rest_stats 函数中。
因为该函数的调用处就是 init 方法中。

为了让 Scoreboard 能够在当前得分下方显示当前等级,我们在 init方法中调用一个新方法:

scoreboard.py:

def __init__(self,ai_settings,screen,stats):
	self.prep_level()

新调用方法定义如下:

	def prep_level(self):
		#将等级转换为渲染的图像
		self.level_image = self.font.render(str(self.stats.level),True,self.text_color,self.ai_settings.bg_color)
		
		#将等级放在得分下方
		self.level_rect = self.level_image.get_rect()
		self.level_rect.right = self.score_rect.right
		self.level_rect.top = self.score_rect.bottom +10

在这里我们让 prep_level 创建一幅图像,并将其 reght 属性设置为得分的right属性。然后top属性设置为比得分图像的bottom属性大10像素,以便得分和等级之间留出一定的空间。

为了让其显示到屏幕上,我们还需要更新一下 show_score() 方法

def show_score(self):
		#在屏幕上显示得分
		self.screen.blit(self.score_image,self.score_rect)
		self.screen.blit(self.high_score_image,self.high_score_rect)
		self.screen.blit(self.level_image,self.level_rect)

我们来看一下等级是否能成功显示到屏幕当中:
在这里插入图片描述

现在虽然成功将等级显示到游戏屏幕中了,可是编辑提高等级的逻辑。

提高等级逻辑如下:

game_functions.py:

def check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets):	
	#检查是否有子弹击中外星人,如果是,删除相应子弹和外星人。
	collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
	
	if len(aliens) ==0:
		bullets.empty()
		ai_settings.increase_speed()
		create_fleet(ai_settings,screen,ship,aliens)
		
		stats.level += 1
		sb.prep_level()

如果一整群的外星人都被成功消灭之后,我们就将 stats.level 的值加1,并调用 prep_level() ,以确保正确地显示新等级。

为了确保点击 play 按钮再次开始游戏时 记分和等级图像能够重置:

game_functions.py

def check_play_button(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets,mouse_x,mouse_y):
		#在玩家单机play按钮时开始游戏
	if button_clicked and not stats.game_active:
		#重置游戏设置
		ai_settings.initialize_dynamic_settings()
		
		#隐藏光标
		pygame.mouse.set_visible(False)
		stats.reset_stats()
		stats.game_active = True
		
		#重置记分牌图像
		sb.prep_score()
		sb.prep_high_score()
		sb.prep_level()

修改调用处:

def check_events(ai_settings,screen,stats,sb,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,sb,play_button,ship,aliens,bullets,mouse_x,mouse_y)
		
			

修改 check_events() 的调用处:
alien_invasion.py:

while True:
		gf.check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets)

测试:
在这里插入图片描述

显示余下的飞船数量

这是《外星人入侵》小项目的最后一个功能点。
显示玩家剩余飞船的数量使用图像而不是数字。为此,我们在屏幕左上角绘制飞船图像来指出还余下多少艘飞船。

让 ship 基础 Sprite ,以便能够创建飞船编组:
ship.py:

from pygame.sprite import Sprite

class Ship(Sprite):
		def __init__(self,ai_settings,screen):
		super(Ship,self).__init__()

修改 Scoreboard,在其中创建一个可供显示的飞船编组。

from pygame.sprite import Group
from ship import Ship

def __init__(self,ai_settings,screen,stats):
	self.prep_ships()

prep_ships 定义如下:

scoreboard.py:

	def prep_ships(self):
		#显示还余下多少艘飞船
		self.ships = Group()
		for ship_number in range(self.stats.ships_left):
			ship = Ship(self.ai_settings,self.screen)
			ship.rect.x = 10 +ship_number * ship.rect.width
			ship.rect.y = 10
			self.ships.add(ship)

将飞船绘制到屏幕上:
scoreboard.py:

	def show_score(self):
		#在屏幕上显示得分
		self.screen.blit(self.score_image,self.score_rect)
		self.screen.blit(self.high_score_image,self.high_score_rect)
		self.screen.blit(self.level_image,self.level_rect)
		self.screen.draw(self.screen)
		

为让玩家知晓游戏开始时自己拥有多少生命值,
在 game_functions.py 的 check_play_button() 中进行调用:

sb.prep_ships()

然后在将玩家控制的飞船与外星人碰撞后的显示进行更新:
game_functions.py:

def update_aliens(ai_settings,screen,stats,sb,ship,aliens,bullets):
	#检查是否有外星人位于屏幕边缘,并更新整群外星人的位置
	check_fleet_edges(ai_settings,aliens)
	
	#更新外新人群中所有外星人的位置
	aliens.update()
	
	
	if pygame.sprite.spritecollideany(ship,aliens):
		#print("Ship hit!!!")
		ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets)
	
	check_aliens_bottom(ai_settings,screen,stats,sb,ship,aliens,bullets)

def ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets):
	if stats.ships_left > 0:
		#响应外星人撞到的飞船
		stats.ships_left -= 1
	
		sb.prep_ships()
		
		#清空外星人列表和子弹列表
		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)

更新调用处:
game_functions.py

def check_aliens_bottom(ai_settings,screen,stats,sb,ship,aliens,bullets):
	#检查是否有外星人到达底部
	screen_rect = screen.get_rect()
	
	for alien in aliens.sprites():
		if alien.rect.bottom >= ship.rect.bottom:
			ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets)
			break

alien_invasion.py:

# while 循环来控制游戏
	while True:
		gf.check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets)
		if stats.game_active:
			ship.update()
			gf.update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets)
			gf.update_aliens(ai_settings,screen,stats,sb,ship,aliens,bullets)
		
		bullets.update()
		gf.update_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,play_button)

在这里插入图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。