上篇文章为大家介绍了《外星人入侵》项目中的最后一个功能记分的部分功能的实现;包括显示得分、创建记分牌、在外星人消灭的时候更新得分、将消灭的每个外星人的点数都计入得分以及最后的提高点数和将得分圆整等。本文给大家介绍记分的其他剩余功能的实现,我们首先介绍的就是最高得分功能的实现。
1、最高得分每个玩家都想超过游戏的最高分记录。下面来跟踪并显示最高得分,给玩家提供要超越的目标。我们将最高分存储在GameStats中:
def __init__(self, ai_settings):
"""初始化統計信息"""
self.ai_settings = ai_settings
self.reset_stats()
# 遊戲剛啟動時處於非活動狀態
self.game_active = False
# 在任何情况下都不应该重置最高得分
self.high_score = 0
鉴于在任何情况下都不会重置最高得分,因此我们在__init__()中而不是reset_stats()中初始化high_score。这点还得初学者特别注意。
接下来修改Scoreboard以显示最高得分。先来修改方法__init__():
def __init__(self, ai_settings, screen, stats):
"""Initialize scorekeeping attributes."""
self.screen = screen
self.screen_rect = screen.get_rect()
self.ai_settings = ai_settings
self.stats = stats
# Font settings for scoring information.
self.text_color = (30, 30, 30)
self.font = pygame.font.SysFont(None, 48)
# 准备初始得分图像
self.prep_score()
self.prep_high_score()
最高得分将与当前得分分开显示,因此,我们需要编写一个新方法prep_high_score(),用于准备包含最高得分的图像。方法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.high_score_rect.top
我们将最高得分圆整到最近的10的整数倍,并添加了用逗号表示的千分位分割符。然后,我们根据最高得分生成一幅图像,使其水平居中,并将其top属性设置为当前得分图像的top属性。
现在,方法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)
为检查是否诞生了新的最高得分,我们在game_funcations.py中添加一个新函数check_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来修饰最高得分图像。我们比较当前得分和最高得分,如果当前得分更高,就更新high_score的值,并调用prep_high_score()来更新包含最高得分的图像。
函数check_bullet_alien_collisions()中。每当有外星人被消灭,都需要在更新得分后调用check_high_score():
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, aliens, bullets):
"""更新子弹的位置,并删除已消失的子弹"""
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
if collisions:
for aliens in collisions.values():
stats.score += ai_settings.alien_points
sb.prep_score()
check_high_score(stats, sb)
if len(aliens) == 0:
bullets.empty()
ai_settings.increase_speed()
create_fleet(ai_settings, screen, ship, aliens)
字典collisions存在时,我们根据消灭了多少外星人来更新得分,在调用check_high_score()。
在第一次玩这款游戏的时候,当前得分就是最高得分,因此,两个地方显示显示的都是当前得分。但再次开始这个游戏的时候,最高得分出现在中央,而当前得分出现在右边,具体如下图所示:
为游戏中显示玩家的等级,首先需要在GameStats中添加了一个表示当前等级的属性。为确保每次开始新游戏时都重置等级,在 reset_stats()中初始化它:
def reset_stats(self):
"""初始化在遊戲運行期間可能變化的統計信息"""
self.ships_left = self.ai_settings.ship_limit
self.score = 0
self.level = 1
为让Scoreboard能够在得分下方显示当前等级,我们在__init__()中调用了一个新方法prep_level()
def __init__(self, ai_settings, screen, stats):
"""Initialize scorekeeping attributes."""
self.screen = screen
self.screen_rect = screen.get_rect()
self.ai_settings = ai_settings
self.stats = stats
# Font settings for scoring information.
self.text_color = (30, 30, 30)
self.font = pygame.font.SysFont(None, 48)
# 准备初始得分图像
self.prep_score()
self.prep_high_score()
self.prep_level()
具体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()根据存储在stats.level中的值创建一副图像,并将其right属性设置为得分的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)
在这个方法中,添加了一行在屏幕上显示等级图像的代码。我们在check_bullet_alien_collisions()中提高等级,并更新等级图像:
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, aliens, bullets):
"""更新子弹的位置,并删除已消失的子弹"""
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
if collisions:
for aliens in collisions.values():
stats.score += ai_settings.alien_points
sb.prep_score()
check_high_score(stats, sb)
if len(aliens) == 0:
bullets.empty()
ai_settings.increase_speed()
# 提高等级
stats.level += 1
sb.prep_level()
create_fleet(ai_settings, screen, ship, aliens)
如果整群外星人都被消灭,我们就将stats.level的值加1,并调用prep_level(),以确保正确正确地显示新等级。
为确保开始新游戏时更新记分和等级图像,在按钮play被单击时触发重置:
def check_play_button(ai_settings, screen, stats, sb, play_button, ship,
aliens, bullets, mouse_x, mouse_y):
"""在玩家单击play按钮时开始新游戏"""
button_checked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_checked and not stats.game_active:
# 重置游戏设置
ai_settings.initialize_dymaic_settings()
# 隐藏光标
pygame.mouse.set_visible(False)
# 重置游戏统计信息
stats.reset_stats()
stats.game_active = True
# 重置记分牌图像
sb.prep_score()
sb.prep_high_score()
sb.prep_level()
# 清空外星人列表和子弹列表
aliens.empty()
bullets.empty()
# 创建一群新的外星人,并让飞船居中
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()
check_play_button()的定义需要包含对象sb。为重置记分牌图像,我们在重置相关游戏设置后调用prep_score()、prep_high_score()和prep_level()。
在check_events()中,现在需要向check_play_button()传递sb,让它能够访问积分牌对象:
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.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)
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ai_settings, screen, ship, bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
check_events()的定义需要包含形参sb,这样调用check_play_buttom()时,才能将sb作为实参传递给它。
最后,更新alien_invasion.py中调用check_events()的代码,也向它传递sb:
def run_game():
# 初始化游戏并创建一个屏幕对象
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("Alian Invasion")
# 创建play按钮
play_button = Button(ai_settings, screen, "Play")
# 創建一個用于存儲遊戲統計信息的實例
stats = GameStats(ai_settings)
sb = Scoreboard(ai_settings, screen, stats)
# 创建一艘飞船、一个子弹编组和一个外星人编组
ship = Ship(ai_settings, screen)
# 创建一组一个用于存储子弹的编组
bullets = Group()
aliens = Group()
# 创建外星人群
# alien = Alien(ai_settings, screen)
gf.create_fleet(ai_settings, screen, ship, aliens)
# 开始游戏的主循环
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, stats, screen, ship, aliens, bullets)
gf.update_screen(ai_settings, screen, stats, sb, ship, aliens,
bullets, play_button)
run_game()
现在我们运行这个游戏,就可以知道我们可以升到多少级了,具体效果如下:
这里需要我们注意的是:在一些经典游戏中,得分带标签,如score、High Score和Level。我们没有显示这些标签,因为开始玩这款游戏后你,每个数字的含义将一目了然。要包含这些标签,只需在Scoreboard中调用font.render()前,将它们添加到得分字符串中即可。
读者看了这么多了,功能应该了解的差不多了,应该对这个游戏有了清晰的认知。最后给大家留个作业: 就是请读者自己实现显示余下的飞船数。这个功能实现和前面差不多,只需要你还得考虑将飞船加入到飞船编组中,并且要将其加到socreboard.py中。最后还得在game_function.py中将sb加入。大家最后不要忘了在alien_invasion.py中将update_alien()中加入参数sb。整个项目的最后一个功能就留给大家实现哈,网上有很多答案,但是还是希望自己去实现,学了这么多了,实践检测一下自己到底学的如何,加油哈,各位!!!!
上篇文章为大家介绍了《外星人入侵》项目中的最后一个功能记分的部分功能的实现;包括显示得分、创建记分牌、在外星人消灭的时候更新得分、将消灭的每个外星人的点数都计入得分以及最后的提高点数和将得分圆整等。本文给大家介绍记分的其他剩余功能的实现,主要包括最高得分以及显示等级。最后还给大家留了一个小作业,就是让大家自己实现显示余下的飞船个数。本项目就要到这里结束了,将近十几篇文章分别给大家循序渐进的给大家介绍本项目每个功能的实现。下一篇文章将会对《外星人入侵》整个项目做一个简单的总结以及整个项目的完整代码,但是还是希望大家能够从这些文章一步步走来,那样你会很扎实,你一步步实现了项目的每个功能,对整个项目的框架有个很清晰的认知,这对你的帮助是巨大的。但是如果你只是简单的粘贴复制代码,一点也没有用。
其实这个项目已经很典型,代码到处都是,但是,如果你只是简单的粘贴复制,对你知识的学习没有任何的价值,你还是得跟着过一遍,然后要知道每行代码的含义或者是用到了前面我们介绍的哪一块知识点,只有这样,这个项目才会发挥不一样的价值,希望大家认真学习,把基础知识打扎实一点。Python是一门注重实际操作的语言,它是众多编程语言中最简单,也是最好入门的。当你把这门语言学会了,再去学习java、go以及C语言就比较简单了。当然,Python也是一门热门语言,对于人工智能的实现有着很大的帮助,因此,值得大家花时间去学习。生命不息,奋斗不止,我们每天努力,好好学习,不断提高自己的能力,相信自己一定会学有所获。加油!!!



