发现问题
在学习《Python编程:从入门到实战(第2版)》中的实战部分,外星人入侵时,做到让外星人移动起来那一块,遇到如下所示的问题:
在不让外星人移动时,外星人能按照预期正确显示出来
但是让外星人移动之后,就只显示一列外星人左右移动并慢慢向下移动:
分析问题
我仔细地对照了书里面地所有代码,确定自己的代码没有问题,我就猜到可能是每一行的外星人重叠在一起了,为了验证我的猜想,我在_check_fleet_edges()
方法里面加了两行代码,打印出每个外星人的坐标
def _check_fleet_edges(self):
"""有外星人到达边缘时采取相应的措施"""
for alien in self.aliens.sprites():
print(f"x: {alien.rect.x}, y: {alien.rect.y}")
if alien.check_edges():
self._change_fleet_direction()
break
print("------------------------")
打印出来的结果确实印证了我的猜想:
每一行都有七个外星人,每个外星人的x坐标都是一样的。
至于为什么动起来就会重叠,不动就不重叠,通过debug调式_check_fleet_edges()
方法得知,在一开始,每个外星人的位置确实不是重叠的:
后面为什么又重叠在一起了呢。应该是在alien.py中的update()
方法没有正确地更新外星人的位置。没有考虑每行外星人之间的相对位置,所以它们就会逐渐重叠。但是update()
方法内容是没有错的。
所以该怎么解决问题,尝试了很多次,都没办法解决,最后我修改了代码,得出以下解决方案。
解决问题
在我的Alien
类的__init__()
方法中,我设置了每个外星人的初始位置为其图像的宽度和高度,这意味着所有外星人的初始位置都相同,即位于屏幕的左上角附近。这会导致在屏幕上显示时,它们会重叠在一起。
# 每个外星人最初都在屏幕左上角附近
self.rect.x = self.rect.width
self.rect.y = self.rect.height
因此需要在创建外星人时给它们分配不同的初始位置。在Alien
类的__init__
方法做如下修改,以便它不使用固定的初始位置(self.rect.x = self.rect.width 和 self.rect.y = self.rect.height),而是使用在_create_alien
方法中计算得到的位置。
def __init__(self, ai_game, x, y):
"""初始化外星人并设置其起始位置"""
super().__init__()
self.screen = ai_game.screen
self.settings = ai_game.settings
# # get_rect()访问屏幕属性rect,这让我们能够将外星人放到屏幕的正确位置
# self.screen_rect = ai_game.screen.get_rect()
# 加载外星人图像,并设置其rect属性
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect(topleft=(x, y)) # 使用传入的x和y坐标来设置rect的位置
self.width, self.height = self.rect.size # 记录外星人图像宽度和高度
# 每个外星人最初都在屏幕左上角附近
# self.rect.x = self.rect.width
# self.rect.y = self.rect.height
# 存储外星人的准确水平位置
self.x = float(x)
并在alien_invasion.py中相应位置做修改,就可以正确显示出所有外星人了