《Alien Invasion》游戏外星舰队无法正常移动问题求助
《Alien Invasion》外星舰队移动异常问题排查
我在学习Python并开发《Alien Invasion》游戏时,外星舰队向右移动功能出现异常,具体表现为:
- 舰队完全无法移动
- 偶尔能移动时,仅边缘外星人动、其余静止,或整体移动状态混乱
以下是游戏相关代码,恳请帮忙排查问题:
alien_invasion.py
import sys import pygame from settings import settings from ship import Ship from bullets import Bullet from alien import Alien class AlienInvasion: """overall class to manage game assets and behaviours""" def __init__(self): """initialise game and create game resources""" pygame.init() self.settings=settings() self.screen=pygame.display.set_mode((self.settings.screen_width,self.settings.screen_height)) pygame.display.set_caption("Alien Invasion") self.ship=Ship(self) self.bullets=pygame.sprite.Group() self.aliens=pygame.sprite.Group() def run_game(self): """start main loop for the game""" while True: self._check_events() self.ship.update() self._update_bullets() self._create_fleet() self._update_screen() self._update_aliens() def _check_events(self): #watch for keyboard and mouse events. for event in pygame.event.get(): if event.type==pygame.QUIT: sys.exit() elif event.type==pygame.KEYDOWN: self._check_KEYDOWN_events(event) elif event.type==pygame.KEYUP: self._check_KEYUP_events(event) def _check_KEYDOWN_events(self,event): """respond to keypresses.""" if event.key==pygame.K_RIGHT: self.ship.moving_right=True elif event.key==pygame.K_LEFT: self.ship.moving_left=True elif event.key==pygame.K_SPACE: self._fire_bullet() elif event.key==pygame.K_q: sys.exit() elif event.key==pygame.K_f: self.screen=pygame.display.set_mode((0,0),pygame.FULLSCREEN) self.settings.screen_width=self.screen.get_rect().width self.settings.screen_height=self.screen.get_rect().height def _check_KEYUP_events(self,event): """respond to key releases.""" if event.key==pygame.K_RIGHT: self.ship.moving_right=False elif event.key==pygame.K_LEFT: self.ship.moving_left=False def _fire_bullet(self): """create a new bullet and add it to the bullet group""" if len(self.bullets) < (self.settings.bullets_allowed): new_bullet=Bullet(self) self.bullets.add(new_bullet) def _update_bullets(self): """Update position of bullets and get rid of old bullets.""" self.bullets.update() for bullet in self.bullets.copy(): if bullet.rect.bottom <= 0: self.bullets.remove(bullet) def _update_aliens(self): """initialise right movement of aliens to right""" self.aliens.update() def _create_fleet(self): """create the fleet of aliens""" alien=Alien(self) alien_width, alien_height= alien.rect.size alien_width=alien.rect.width available_space_x=self.settings.screen_width-(2*alien_width) number_aliens_x=available_space_x//(2*alien_width) ship_height=self.ship.rect.height available_space_y = (self.settings.screen_height - (3 * alien_height) - ship_height) number_rows = available_space_y // (2 * alien_height) for row_number in range(number_rows): for alien_number in range(number_aliens_x): self._create_alien(alien_number, row_number) def _create_alien(self,alien_number, row_number): alien=Alien(self) alien_width, alien_height= alien.rect.size alien_width=alien.rect.width alien.x=alien_width + 2 * alien_width * alien_number alien.rect.x=alien.x alien.rect.y=alien.rect.height + 2 * alien.rect.height * row_number self.aliens.add(alien) def _check_fleet_edges(self): """respond appropriately if any aliens have reached the edge""" for alien in self.aliens.sprites(): if alien.check_edges(): self._change_fleet_direction() break def _change_fleet_direction(self): """drop entire fleet and change direction""" for alien in self.aliens.sprites(): alien.rect.y += self.settings.fleet_drop_speed self.settings.fleet_direction *= -1 def _update_screen(self): """update images on the screen and flip to the new screen.""" self.screen.fill(self.settings.bg_color) self.ship.blitme() for bullet in self.bullets.sprites(): bullet.draw_bullet() self.aliens.draw(self.screen) pygame.display.flip() if __name__=='__main__': ai=AlienInvasion() ai.run_game()
ship.py
import pygame class Ship: """a class to manage the ship""" def __init__(self,ai_game): """initialize the ship and set its starting position.""" self.screen=ai_game.screen self.settings=ai_game.settings self.screen_rect=ai_game.screen.get_rect() self.image=pygame.image.load('images/ship.bmp') self.rect=self.image.get_rect() self.rect.midbottom=self.screen_rect.midbottom self.x=float(self.rect.x) self.moving_right=False self.moving_left=False def update(self): if self.moving_right and self.rect.right < self.screen_rect.right: self.x += self.settings.ship_speed if self.moving_left and self.rect.left > 0: self.x -= self.settings.ship_speed self.rect.x=self.x def blitme(self): """draw the ship st its current location.""" self.screen.blit(self.image,self.rect)
alien.py
import pygame from settings import settings from pygame.sprite import Sprite class Alien(Sprite): """A class to represent a single alien in the fleet.""" def __init__(self,ai_game): """initialise alien and set its starting position""" super().__init__() self.screen=ai_game.screen self.settings=ai_game.settings self.image=pygame.image.load('images/corona.bmp') self.rect=self.image.get_rect() self.rect.x=self.rect.width self.rect.y=self.rect.height self.x=float(self.rect.x) def check_edges(self): """Return True if alien is at edge of screen.""" screen_rect = self.screen.get_rect() if self.rect.right >= screen_rect.right or self.rect.left<=0: return True def update(self): """make the aliens move right""" self.x += (self.settings.alien_speed * self.settings.fleet_direction) self.rect.x=self.x
settings.py
class settings: """a class to store all settings for alien invasion.""" def __init__(self): """initialise game's settings""" self.screen_width=1250 self.screen_height=650 self.bg_color=(103,113,214) self.bullets_allowed=10 self.bullet_speed=8 self.bullet_height=15 self.bullet_width=3 self.bullet_color=(255,0,0) self.ship_speed=1.5 self.alien_speed=1.0 self.fleet_drop_speed=15 self.fleet_direction=1
bullets.py
import pygame from pygame.sprite import Sprite class Bullet(Sprite): """A class to manage bullets fired from the ship""" def __init__(self,ai_game): """create a bullet object at ship's current position""" super().__init__() self.screen=ai_game.screen self.settings=ai_game.settings self.color=self.settings.bullet_color self.rect=pygame.Rect(0,0,self.settings.bullet_width,self.settings.bullet_height) self.rect.midtop=ai_game.ship.rect.midtop self.y=float(self.rect.y) def update(self): """move the bullet up the screen""" self.y -= self.settings.bullet_speed self.rect.y=self.y def draw_bullet(self): """draw the bullet to the screen""" pygame.draw.rect(self.screen,self.color,self.rect)
问题排查与修复方案
核心问题
- 重复创建外星舰队:
run_game主循环中每帧都调用_create_fleet(),导致不断生成新外星人覆盖已移动的外星人,表现为舰队不动或仅新生成的边缘外星人短暂移动。 - 外星人更新逻辑缺失边缘检测:
_update_aliens()仅更新位置,未先检查舰队是否触达屏幕边缘,方向切换逻辑未生效。 - 主循环执行顺序错误:
_update_aliens()在_update_screen()之后执行,导致外星人位置更新后未及时渲染。
修复代码
修改alien_invasion.py的初始化与主循环
将舰队创建移到初始化阶段,调整主循环执行顺序:
def __init__(self): """initialise game and create game resources""" pygame.init() self.settings=settings() self.screen=pygame.display.set_mode((self.settings.screen_width,self.settings.screen_height)) pygame.display.set_caption("Alien Invasion") self.ship=Ship(self) self.bullets=pygame.sprite.Group() self.aliens=pygame.sprite.Group() self._create_fleet() # 初始化时仅创建一次舰队 def run_game(self): """start main loop for the game""" while True: self._check_events() self.ship.update() self._update_bullets() self._update_aliens() # 先更新外星人位置 self._update_screen() # 再渲染屏幕
修改alien_invasion.py的_update_aliens方法
加入边缘检测逻辑:
def _update_aliens(self): """检查是否有外星人到达边缘,再更新所有外星人位置""" self._check_fleet_edges() self.aliens.update()
修改后,外星舰队会正常移动,触达屏幕边缘时自动下降并切换方向,不会再出现移动异常问题。
内容的提问来源于stack exchange,提问作者tejasvi-23
相关产品推荐
相关产品推荐

