pygame精灵的移动代码无法正常工作



我正在尝试使用Pygame创建一个Space Invaders克隆作为类项目的一部分。我在让外星人正确移动方面遇到了一些问题。

外星人应该到达边界,向下移动屏幕,他们的方向变量应该改变(1代表右,2代表左)。如果方向变量是正确的,它们将沿着屏幕向右移动,反之亦然,向左移动,直到它们到达另一个边界并再次向下移动屏幕,在一个连续的循环中。

我用 Alien 类的单个实例处理了这个,但是当尝试集成到组设置中时,它似乎根本不起作用......

为了尝试提供帮助,我添加了一个"标志"变量,因为我认为问题可能在于所有外星人的运动都基于第一个撞到"墙"的外星人的运动,但我不确定它是否比方向变量更有帮助......

(请原谅混乱和缺乏称职的评论!

import pygame
import sys
class Fighter(pygame.sprite.Sprite):
def __init__(self,life):
pygame.sprite.Sprite.__init__(self)
fighterImage = pygame.image.load("..GraphicsFighterSprite.png").convert_alpha() #convert alpha makes imgs transparent
self.image = pygame.Surface([32,32])
self.image.set_colorkey(black) # makes surfaces transparent
self.image.blit(fighterImage, (0,0))
self.life = 3
self.rect = self.image.get_rect()
self.rect.x = 300
self.rect.y = 700
def move_ship(self, direction, pixels):
if direction == 1 and self.rect.x <=560:
self.rect.x += pixels
if direction == 2 and self.rect.x >=10:
self.rect.x -= pixels
class Alien(pygame.sprite.Sprite):
def __init__(self,alive,x):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([32,32])
self.image.set_colorkey(black)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = 400 #about midway down screen for testing purposes
alienSprite = pygame.image.load("..GrpahicsEnemyAlien1Static.png")
self.image.blit(alienSprite, (0,0))
self.alive = True
def update(self,directional,flag):
if self.rect.x >= 560:
directonal = 2 #sets the direction to "left"
flag = "LEFT" #sets the flag to "left" so all other aliens know
self.rect.y = self.rect.y+10 #moves alien down the screen
elif self.rect.x <= 10:
directional = 1 #sets the direction to "right"
flag = "RIGHT" #sets the flag to "right" so all other aliens know
self.rect.y = self.rect.y+10
if directional == 1 or flag == "RIGHT":
self.rect.x += 1 #aliens move to the right
else:
self.rect.x -= 1 #aliens move to the left
return directional, flag #updates direction of aliens for each loop
def kill(self):
self.alive = False
pygame.init()
screen = pygame.display.set_mode([600,800])
pygame.display.set_caption("Space Invaders")
background_image = pygame.image.load("..Graphicsspaceinvbackground.png")
background_image = pygame.transform.scale(background_image, (600,800))
pygame.mouse.set_visible(False)
done = False
clock = pygame.time.Clock()
black = (0,0,0)
white = (255,255,255)
green = (122,240,112)
bullets = []
bulletgraphic = pygame.image.load("..GraphicsFighterBullet.png")
bulletgraphic = pygame.transform.scale(bulletgraphic, (32,32))
direction = 0
directional = 1 #sets initial direction to right
flag = "RIGHT" #sets initial flag to right
score = 0
fighter_pilot = Fighter(True)
player = pygame.sprite.Group()
player.add(fighter_pilot)
alien = Alien(True,1,300)
alien1 = Alien(True,1,350)
alien2 = Alien(True,1,400)
alien3 = Alien(True,1,450)
alien4 = Alien(True,1,500)
alien5 = Alien(True,1,550)
aliens = pygame.sprite.Group() #this is the group in which all the alien enemies are in
aliens.add(alien,alien1,alien2,alien3,alien4,alien5)
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if len(aliens) == 0: 
done = True 
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
direction = 1
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
direction = 2
if event.key == pygame.K_SPACE:
bullets.append([(fighter_pilot.rect.x+13), fighter_pilot.rect.y]) #x value is roughly centre of ship, y value is same as ship
fired = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or event.key == pygame.K_d or event.key == pygame.K_LEFT or event.key == pygame.K_a: # only works on key up for left/right arrows & A/D keys
direction = 0
fighter_pilot.move_ship(direction, 5)
directional = aliens.update(directional, flag) #this line updates the aliens direction with every time the program loops
for b in range(len(bullets)):
bullets[b][1]-=10
if fired == True:
if alien.rect.x >= (fighter_pilot.rect.x+13)-22 and alien.rect.x <= (fighter_pilot.rect.x+13)+22 and alien.alive == True:
if alien.rect.y == bullets[b][1]:
aliens.remove(alien)
alien.kill()
bullets.pop()
score = score + 100
if alien1.rect.x >= (fighter_pilot.rect.x+13)-22 and alien1.rect.x <= (fighter_pilot.rect.x+13)+22 and alien1.alive == True:
if alien1.rect.y == bullets[b][1]:
aliens.remove(alien1)
alien1.kill()
bullets.pop()
score = score + 100
if alien2.rect.x >= (fighter_pilot.rect.x+13)-22 and alien2.rect.x <= (fighter_pilot.rect.x+13)+22 and alien2.alive == True:
if alien2.rect.y == bullets[b][1]:
aliens.remove(alien2)
alien2.kill()
bullets.pop()
score = score + 100
if alien3.rect.x >= (fighter_pilot.rect.x+13)-22 and alien3.rect.x <= (fighter_pilot.rect.x+13)+22 and alien3.alive == True:
if alien3.rect.y == bullets[b][1]:
aliens.remove(alien3)
alien3.kill()
bullets.pop()
score = score + 100
if alien4.rect.x >= (fighter_pilot.rect.x+13)-22 and alien4.rect.x <= (fighter_pilot.rect.x+13)+22 and alien4.alive == True:
if alien4.rect.y == bullets[b][1]:
aliens.remove(alien4)
alien4.kill()
bullets.pop()
score = score + 100
if alien5.rect.x >= (fighter_pilot.rect.x+13)-22 and alien5.rect.x <= (fighter_pilot.rect.x+13)+22 and alien5.alive == True:
if alien5.rect.y == bullets[b][1]:
aliens.remove(alien5)
alien5.kill()
bullets.pop()
score = score + 100
for bullet in bullets:
if bullet[0]<0:
bullets.pop()
screen.blit(background_image, (0,0))
for bullet in bullets:
screen.blit(bulletgraphic, pygame.Rect(bullet[0], bullet[1], 0, 0))
aliens.draw(screen)
player.draw(screen)
scoreImg = font.render(str(score),1,green)
screen.blit(scoreImg, (10,10))
pygame.display.flip()
clock.tick(60)
pygame.quit()

我真的无法弄清楚为什么这不起作用 - 但是如果您在一个外星人上使用更新功能,它确实有效?

提前谢谢。

我已经修改并修复了您的代码。我发现的主要问题是代码有一些逻辑错误和不必要的变量,这些错误只会使代码膨胀并使其更难理解。

主要问题:

  • 不需要flag变量。
  • 不需要将directional变量传递到update方法中,并且可能会导致错误。
  • directional实际上应该是一个对象字段,而不是类之外的变量。这个变量属于每个外星人更有意义,不是吗。
  • 传递给Alien构造函数的初始y值小于 10,导致Alien在其 x 值大于 10 之前自由落体。
  • 程序中使用了对象font,但未初始化。

不需要flag变量,因为每个Alien都与另一个同步移动。因此,如果Alien一个人知道它必须改变方向,他们都会这样做。

同样,将这两个全局变量传递到update方法中确实不是最好的方法,并且对面向对象没有多大意义。

关于使directional变量全局。这不是一个好的设计决策,让它成为每个单独Alien对象的一部分更具有面向对象的意义。

与我的代码的其他区别:

  • 删除了font对象的使用。
  • 没有渲染任何图像,只是用颜色填充Surfaces
  • 删除了一些在帖子上下文中无用的其他代码。

我希望这个答案对您有所帮助,如果您有任何其他问题,请随时在下面发表评论!

修订后的代码:

import pygame
class Fighter(pygame.sprite.Sprite):
def __init__(self,life):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([32,32])
self.image.set_colorkey(black) # makes surfaces transparent
self.image.fill((0, 255, 0))
self.life = 3
self.rect = self.image.get_rect()
self.rect.x = 300
self.rect.y = 700
def move_ship(self, direction, pixels):
if direction == 1 and self.rect.x <=560:
self.rect.x += pixels
if direction == 2 and self.rect.x >=10:
self.rect.x -= pixels
class Alien(pygame.sprite.Sprite):
def __init__(self,alive,x,y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([32,32])
self.image.set_colorkey(black)
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y #about midway down screen for testing purposes
self.alive = True
self.directional = 1
def update(self):
if self.rect.x >= 560:
self.directional = 2
self.rect.y += 10
elif self.rect.x <= 10:
self.directional = 1
self.rect.y += 10

if self.directional == 1:
self.rect.x += 1 #aliens move to the right
else:
self.rect.x -= 1 #aliens move to the left
def kill(self):
self.alive = False
pygame.init()
window_width = 600
window_height = 800
screen = pygame.display.set_mode([window_width,window_height])
done = False
black = (0,0,0)
white = (255,255,255)
green = (122,240,112)
bullets = []
bulletgraphic = pygame.Surface((32, 32))
bulletgraphic.fill((0, 0, 200))
direction = 0
score = 0
fighter_pilot = Fighter(True)
player = pygame.sprite.Group()
player.add(fighter_pilot)
alien = Alien(True,20,300)
alien1 = Alien(True,20,350)
alien2 = Alien(True,20,400)
alien3 = Alien(True,20,450)
alien4 = Alien(True,20,500)
alien5 = Alien(True,20,550)
aliens = pygame.sprite.Group() #this is the group in which all the alien enemies are in
aliens.add(alien,alien1,alien2,alien3,alien4,alien5)
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if len(aliens) == 0: 
done = True 
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
direction = 1
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
direction = 2
if event.key == pygame.K_SPACE:
bullets.append([(fighter_pilot.rect.x+13), fighter_pilot.rect.y]) #x value is roughly centre of ship, y value is same as ship
fired = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or event.key == pygame.K_d or event.key == pygame.K_LEFT or event.key == pygame.K_a: # only works on key up for left/right arrows & A/D keys
direction = 0
fighter_pilot.move_ship(direction, 5)
aliens.update() #this line updates the aliens direction with every time the program loops
for b in range(len(bullets)):
bullets[b][1]-=10
if fired == True:
if alien.rect.x >= (fighter_pilot.rect.x+13)-22 and alien.rect.x <= (fighter_pilot.rect.x+13)+22 and alien.alive == True:
if alien.rect.y == bullets[b][1]:
aliens.remove(alien)
alien.kill()
bullets.pop()
score = score + 100
if alien1.rect.x >= (fighter_pilot.rect.x+13)-22 and alien1.rect.x <= (fighter_pilot.rect.x+13)+22 and alien1.alive == True:
if alien1.rect.y == bullets[b][1]:
aliens.remove(alien1)
alien1.kill()
bullets.pop()
score = score + 100
if alien2.rect.x >= (fighter_pilot.rect.x+13)-22 and alien2.rect.x <= (fighter_pilot.rect.x+13)+22 and alien2.alive == True:
if alien2.rect.y == bullets[b][1]:
aliens.remove(alien2)
alien2.kill()
bullets.pop()
score = score + 100
if alien3.rect.x >= (fighter_pilot.rect.x+13)-22 and alien3.rect.x <= (fighter_pilot.rect.x+13)+22 and alien3.alive == True:
if alien3.rect.y == bullets[b][1]:
aliens.remove(alien3)
alien3.kill()
bullets.pop()
score = score + 100
if alien4.rect.x >= (fighter_pilot.rect.x+13)-22 and alien4.rect.x <= (fighter_pilot.rect.x+13)+22 and alien4.alive == True:
if alien4.rect.y == bullets[b][1]:
aliens.remove(alien4)
alien4.kill()
bullets.pop()
score = score + 100
if alien5.rect.x >= (fighter_pilot.rect.x+13)-22 and alien5.rect.x <= (fighter_pilot.rect.x+13)+22 and alien5.alive == True:
if alien5.rect.y == bullets[b][1]:
aliens.remove(alien5)
alien5.kill()
bullets.pop()
score = score + 100
for bullet in bullets:
if bullet[0]<0:
bullets.pop()
screen.fill(black)

for bullet in bullets:
screen.blit(bulletgraphic, pygame.Rect(bullet[0], bullet[1], 0, 0))
aliens.draw(screen)
player.draw(screen)
pygame.display.flip()
pygame.quit()
quit()

最新更新