Python Crash Course 第二版侧射游戏:外星人舰队边缘检测仅对顶排生效求助
问题根因定位
当前遇到的边缘检测失效、仅顶排外星人触发判断的问题,是三个叠加的逻辑错误导致的:
- 生成舰队时的空间计算错误,导致最底排外星人初始位置就在屏幕外,触发了连锁的检测顺序问题
- 边缘检测的遍历顺序导致提前break,根本没机会检查到非顶排外星人的边缘状态
- 方向反转后的位置同步逻辑缺失,导致位置判断持续失准
1. 修正舰队生成时的空间计算逻辑
当前_create_fleet里计算纵向可容纳行数时,错误地给可用空间加了2倍的外星人高度,导致算出的行数比屏幕实际能容纳的多,最底排外星人从生成时就完全超出屏幕底部。
修正后的空间计算逻辑:
def _create_fleet(self): """Create the fleet of aliens.""" alien = Alien(self) alien_width = alien.rect.width alien_height = alien.rect.height ship_width = self.ship.rect.width # 修正:x方向(舰队左移方向)的可用空间,扣除左侧飞船预留区域 available_space_x = self.settings.screen_width - (2 * alien_width) - ship_width number_columns = available_space_x // (2 * alien_width) # 修正:y方向(外星人上下移动方向)的可用空间,扣除上下边距 available_space_y = self.settings.screen_height - (2 * alien_height) number_rows = available_space_y // (2 * alien_height) # 按行列生成外星人,避免初始位置超出屏幕 for row_number in range(number_rows): for column_number in range(number_columns): self._create_alien(column_number, row_number)
2. 修正_create_alien的位置赋值逻辑
修正变量名混淆问题,明确x坐标(从右往左排)和y坐标(从上往下排)的映射关系:
def _create_alien(self, column_number, row_number): """Create an alien and place it in the row.""" alien = Alien(self) alien_width = alien.rect.width alien_height = alien.rect.height # x坐标:从屏幕右侧开始,从右往左排列 alien.rect.x = self.settings.screen_width - (2 * alien_width) - (2 * alien_width) * column_number # y坐标:从顶部开始,从上往下排列 alien.y = alien_height + 2 * alien_height * row_number alien.rect.y = alien.y self.aliens.add(alien)
3. 修正边缘检测的逻辑漏洞
当前_check_fleet_edges遍历外星人时,由于外星人是按“顶排先加入组”的顺序存储的,向上移动时永远是顶排外星人最先碰到屏幕上边缘,直接触发反转逻辑,根本遍历不到下方的外星人——这就是观察到“只有顶排外星人触发判断”的核心原因。
修正后的逻辑:
def _check_fleet_edges(self): """Respond appropriately if any aliens have reached an edge.""" edge_touched = False for alien in self.aliens.sprites(): if alien.check_edges(): edge_touched = True break if edge_touched: self._change_fleet_direction()
注:修正初始生成位置后,所有外星人的初始位置都在屏幕内,上下移动时无论是顶排碰上边还是底排碰下边,都会被正确检测,不会出现初始位置超出屏幕导致的长期漏检。
4. 修正check_edges的返回值逻辑
补充显式的False返回,避免隐式返回值带来的判断异常:
# alien.py 内的方法 def check_edges(self): """Return True if alien is at edge of screen.""" screen_rect = self.screen.get_rect() if self.rect.bottom >= screen_rect.bottom or self.rect.top <= 0: return True return False
5. 修正_change_fleet_direction的位置同步逻辑
当前方法在调整x方向位置时,只修改了rect.x,没有同步浮点数属性,长期运行会出现位置漂移;同时需要在触发边缘时,把超出屏幕的y值拉回合法范围,避免位置失准:
def _change_fleet_direction(self): """Drop the entire fleet and change the fleet's direction""" screen_rect = self.screen.get_rect() for alien in self.aliens.sprites(): # 舰队整体左移 alien.rect.x -= self.settings.fleet_left_speed alien.x = float(alien.rect.x) # 同步x的浮点属性 # 把超出屏幕上下边界的y值拉回合法范围 if alien.rect.bottom >= screen_rect.bottom: alien.y = screen_rect.bottom - alien.rect.height if alien.rect.top <= 0: alien.y = alien.rect.height alien.rect.y = alien.y # 反转上下移动的方向 self.settings.fleet_direction *= -1
6. 补充alien.update内的边界保护
在每帧更新位置时,额外加一层边界保护,避免极端情况下外星人飞出屏幕:
# alien.py 内的方法 def update(self): """Move the alien up or down.""" screen_rect = self.screen.get_rect() self.y += (self.settings.alien_speed * self.settings.fleet_direction) # 边界保护:不允许外星人飞出屏幕上下边 if self.y <= 0: self.y = 0 if self.y >= screen_rect.height - self.rect.height: self.y = screen_rect.height - self.rect.height self.rect.y = self.y
内容的提问来源于stack exchange,提问作者Vegpy
相关产品推荐
相关产品推荐

