关于“Python”的核心知识点整理大全40

2024-01-19 09:09:31 浏览数 (1)

14.3.2 创建记分牌

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

代码语言:javascript复制
--snip--
from game_stats import GameStats
from scoreboard import Scoreboard
--snip--
def run_game():
 --snip--
 # 创建存储游戏统计信息的实例,并创建记分牌
 stats = GameStats(ai_settings)
1 sb = Scoreboard(ai_settings, screen, stats)
--snip--
# 开始游戏主循环
while True:
 --snip--
2 gf.update_screen(ai_settings, screen, stats, sb, ship, aliens, 
 bullets, play_button)
run_game() 

我们导入新创建的类Scoreboard,并在创建实例stats后创建了一个名为sb的Scoreboard实例 (见1)。接下来,我们将sb传递给update_screen(),让它能够在屏幕上显示得分(见2)。 为显示得分,将update_screen()修改成下面这样: game_functions.py

代码语言:javascript复制
def update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets,
 play_button):
 --snip--
 # 显示得分
 sb.show_score()
 # 如果游戏处于非活动状态,就显示Play按钮
 if not stats.game_active:
 play_button.draw_button()
 # 让最近绘制的屏幕可见
 pygame.display.flip()

我们在update_screen()的形参列表中添加了sb,并在绘制Play按钮前调用show_score。 如果现在运行这个游戏,你将在屏幕右上角看到0(当前,我们只想在进一步开发记分系统 前确认得分出现在正确的地方)。图14-2显示了游戏开始前的得分。

下面来指定每个外星人值多少点!

14.3.3 在外星人被消灭时更新得分

为在屏幕上实时地显示得分,每当有外星人被击中时,我们都更新stats.score的值,再调 用prep_score()更新得分图像。但在此之前,我们需要指定玩家每击落一个外星人都将得到多少 个点: settings.py

代码语言:javascript复制
def initialize_dynamic_settings(self):
 --snip--
 # 记分
 self.alien_points = 50

随着游戏的进行,我们将提高每个外星人值的点数。为确保每次开始新游戏时这个值都会被 重置,我们在initialize_dynamic_settings()中设置它。 在check_bullet_alien_collisions()中,每当有外星人被击落时,都更新得分: game_functions.py

代码语言:javascript复制
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,
 aliens, bullets):
 """响应子弹和外星人发生碰撞"""
 # 删除发生碰撞的子弹和外星人
 collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
 if collisions:
1 stats.score  = ai_settings.alien_points
 sb.prep_score()
 --snip-- 

我们更新check_bullet_alien_collisions()的定义,在其中包含了形参stats和sb,让它能够 更新得分和记分牌。有子弹撞到外星人时,Pygame返回一个字典(collisions)。我们检查这个 字典是否存在,如果存在,就将得分加上一个外星人值的点数(见)。接下来,我们调用 prep_score()来创建一幅显示最新得分的新图像。 我们需要修改update_bullets(),确保在函数之间传递合适的实参: game_functions.py

代码语言:javascript复制
def update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets):
 """更新子弹的位置,并删除已消失的子弹"""
 --snip--
 check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,
 aliens, bullets) 

在update_bullets()的定义中,需要新增形参stats和sb,而调用check_bullet_alien_collisions()时,也需要传递实参stats和sb。 我们还需要修改主while循环中调用update_bullets()的代码: alien_invasion.py

代码语言:javascript复制
# 开始游戏主循环
 while True:
 gf.check_events(ai_settings, screen, stats, play_button, ship,
 aliens, bullets)
 if stats.game_active:
 ship.update()
 gf.update_bullets(ai_settings, screen, stats, sb, ship, aliens,
 bullets)
 --snip-- 

调用update_bullets()时,需要传递实参stats和sb。 如果你现在运行这个游戏,得分将不断增加!

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

当前,我们的代码可能遗漏了一些被消灭的外星人。例如,如果在一次循环中有两颗子弹射 中了外星人,或者因子弹更宽而同时击中了多个外星人,玩家将只能得到一个被消灭的外星人的 点数。为修复这种问题,我们来调整检测子弹和外星人碰撞的方式。 在check_bullet_alien_collisions()中,与外星人碰撞的子弹都是字典collisions中的一个 键;而与每颗子弹相关的值都是一个列表,其中包含该子弹撞到的外星人。我们遍历字典 collisions,确保将消灭的每个外星人的点数都记入得分: game_functions.py

代码语言:javascript复制
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,
 aliens, bullets):
 --snip--
 if collisions:
1 for aliens in collisions.values():
 stats.score  = ai_settings.alien_points * len(aliens)
 sb.prep_score()
 --snip-- 

如果字典collisions存在,我们就遍历其中的所有值。别忘了,每个值都是一个列表,包含 被同一颗子弹击中的所有外星人。对于每个列表,都将一个外星人的点数乘以其中包含的外星人 数量,并将结果加入到当前得分中。为测试这一点,请将子弹宽度改为300像素,并核实你得到 了更宽的子弹击中的每个外星人的点数,再将子弹宽度恢复到正常值。

14.3.5 提高点数

玩家每提高一个等级,游戏都变得更难,因此处于较高的等级时,外星人的点数应更高。为实现这种功能,我们添加一些代码,以在游戏节奏加快时提高点数: settings.py

代码语言:javascript复制
class Settings():
 """存储游戏《外星人入侵》的所有设置的类"""
 def __init__(self):
 --snip--
 # 加快游戏节奏的速度
 self.speedup_scale = 1.1
 # 外星人点数的提高速度
1 self.score_scale = 1.5
 self.initialize_dynamic_settings()
 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
2 self.alien_points = int(self.alien_points * self.score_scale) 

我们定义了点数提高的速度,并称之为score_scale(见)。很小的节奏加快速度(1.1)让 游戏很快就变得极具挑战性,但为让记分发生显著的变化,需要将点数的提高速度设置为更大的 值(1.5)。现在,我们在加快游戏节奏的同时,提高了每个外星人的点数。为让点数为整数,我 们使用了函数int()。 为显示外星人的点数,我们在Settings的方法increase_speed()中添加了一条print语句: settings.py

代码语言:javascript复制
 def increase_speed(self):
 --snip--
 self.alien_points = int(self.alien_points * self.score_scale)
 print(self.alien_points) 

现在每当提高一个等级时,你都会在终端窗口看到新的点数值.


注意

确认点数在不断增加后,一定要删除这条print语句,否则它可能会影响游戏的性能以及 分散玩家的注意力。


14.3.6 将得分圆整

大多数街机风格的射击游戏都将得分显示为10的整数倍,下面让我们的记分系统遵循这个原 则。我们还将设置得分的格式,在大数字中添加用逗号表示的千位分隔符。我们在Scoreboard中执行这种修改: scoreboard.py

代码语言:javascript复制
 def prep_score(self):
 """将得分转换为渲染的图像"""
1 rounded_score = int(round(self.stats.score, -1))
2 score_str = "{:,}".format(rounded_score)
 self.score_image = self.font.render(score_str, True, self.text_color,
 self.ai_settings.bg_color)
 --snip-- 

函数round()通常让小数精确到小数点后多少位,其中小数位数是由第二个实参指定的。然 而,如果将第二个实参指定为负数,round()将圆整到最近的10、100、1000等整数倍。1处的代 码让Python将stats.score的值圆整到最近的10的整数倍,并将结果存储到rounded_score中。


注意

在Python 2.7中,round()总是返回一个小数值,因此我们使用int()来确保报告的得分为 整数。如果你使用的是Python 3,可省略对int()的调用。


2处使用了一个字符串格式设置指令,它让Python将数值转换为字符串时在其中插入逗号, 例如,输出1,000,000而不是1000000。如果你现在运行这个游戏,看到的将是10的整数倍的整洁 得分,即便得分很高亦如此,如图14-3所示。

14.3.7 最高得分

每个玩家都想超过游戏的最高得分记录。下面来跟踪并显示最高得分,给玩家提供要超越的 目标。我们将最高得分存储在GameStats中: game_stats.py

代码语言:javascript复制
 def __init__(self, ai_settings):
 --snip--
 # 在任何情况下都不应重置最高得分
 self.high_score = 0 

鉴于在任何情况下都不会重置最高得分,我们在__init__()中而不是reset_stats()中初始化 high_score。 下面来修改Scoreboard以显示最高得分。先来修改方法__init__(): scoreboard.py

代码语言:javascript复制
 def __init__(self, ai_settings, screen, stats):
 --snip--
 # 准备包含最高得分和当前得分的图像
 self.prep_score()
1 self.prep_high_score() 

最高得分将与当前得分分开显示,因此我们需要编写一个新方法prep_high_score(),用于准 备包含最高得分的图像(见)。 方法prep_high_score()的代码如下: scoreboard.py

代码语言:javascript复制
 def prep_high_score(self):
 """将最高得分转换为渲染的图像"""
1 high_score = int(round(self.stats.high_score, -1))
2 high_score_str = "{:,}".format(high_score)
3 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()
4 self.high_score_rect.centerx = self.screen_rect.centerx
5 self.high_score_rect.top = self.score_rect.top 

0 人点赞