Pygame碰撞错误Python 3
问题描述:
我目前正在尝试使用Python 3.5.2创建一个简单的空间入侵者Python游戏。目前一切正常,但每当子弹击中我的外星人的一面程序显示错误。 这是代码Pygame碰撞错误Python 3
import pygame
from pygame.locals import *
pygame.init()
width, height = 640, 480
keys=[False, False, False, False]
playerpos=[290,400]
alienpos=[]
bulletpos=[]
for i in range(100, 600, 100):
for j in range(0, 150, 50):
alienpos.append([i, j])
screen = pygame.display.set_mode((width, height))
space = pygame.image.load("space.jpg")
alien = pygame.image.load("alien.png")
bullet = pygame.image.load("bullet.png")
space = pygame.transform.scale(space,(width,height))
player = pygame.image.load("spacecraft.png")
flag1 = 0
flag2 = 0
switch = True
while 1:
screen.fill(0)
screen.blit(space,(0,0))
for i in alienpos:
for j in bulletpos:
if i[1]<=j[1] and i[1]+28 >= j[1] and i[0]<=j[0] and i[0]+28 >= j[0]:
alienpos.remove(i)
screen.blit(alien, i)
if (i[0] + 1) > 600:
flag1 = 1
elif (i[0] - 1) < 1:
flag1 = 0
if flag1 == 0:
i[0] += 1
elif flag1 == 1:
i[0] -= 1
if not len(bulletpos)==0:
for pos in bulletpos:
if pos[1] > 0:
screen.blit(bullet, pos)
pos[1] -= 1
pos=([playerpos[0], playerpos[1]])
screen.blit(player, playerpos)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key==K_w:
keys[0]=True
elif event.key==K_a:
keys[1]=True
elif event.key==K_s:
keys[2]=True
elif event.key==K_d:
keys[3]=True
if event.type == pygame.KEYUP:
if event.key==pygame.K_w:
keys[0]=False
elif event.key==pygame.K_a:
keys[1]=False
elif event.key==pygame.K_s:
keys[2]=False
elif event.key==pygame.K_d:
keys[3]=False
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
if keys[1]:
playerpos[0]-=5
elif keys[3]:
playerpos[0]+=5
elif keys[0]:
bulletpos.append([playerpos[0], playerpos[1]])
当子弹击中了外来的一侧,该程序停止,并出现以下错误。
Traceback (most recent call last):
File "Python35\game.py", line 36, in <module>
alienpos.remove(i)
ValueError: list.remove(x): x not in list
有很多关于在StackOverflow上这个问题类似的问题,但没有的建议一直是任何帮助很大。如果有任何更多的信息,你都需要我会很乐意发表评论。提前致谢!
答
问题是因为你从列表中删除alien
但后来你还检查了这alien
与其他bullets
等bullet
可能与此alien
碰撞并尝试再次同alien
删除 - 但这alien
不存在于名单。
您可以使用break
离开for-loop并跳过检查与其他bullets
的碰撞。
for j in bulletpos:
if i[1]<=j[1] and i[1]+28 >= j[1] and i[0]<=j[0] and i[0]+28 >= j[0]:
alienpos.remove(i)
break
BTW:你能组织这样的代码:
我用pygame.Rect()
(.get_rect()
),以保持对象的位置,然后我可以使用pygame的功能来检查碰撞。
pygame.Rect()
具有性能left
,right
,top
,bottom
,center
等,所以它更容易比较的位置 - 在屏幕上即player_rect.right == screen_rect.right
,或把中心player_rect.center = screen_rect.center
Pygame的具有功能pygame.key.get_pressed()
和你没有创建自己的列表keys
我只使用事件来发射子弹,因为pygame.key.get_pressed()
当我按住按钮时会发射子弹。但是当我一直按下时,我只想射击一次。
import pygame
# --- constants --- (UPPER_CASE names)
WIDTH = 640
HEIGHT = 480
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
# --- main --- (lower_case names)
# - init -
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen_rect = screen.get_rect()
# - objects -
background = pygame.image.load("space.jpg")
background = pygame.transform.scale(background, (WIDTH, HEIGHT))
alien = pygame.image.load("alien.png")
bullet = pygame.image.load("bullet.png")
aliens = []
bullets = []
for x in range(100, 600, 100):
for y in range(0, 150, 50):
aliens.append(alien.get_rect(x=x, y=y))
player = pygame.image.load("spacecraft.png")
player_rect = player.get_rect(x=290, y=400)
# - other -
move_right = True
# - mainloop -
while True:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
#exit(0)
elif event.type == pygame.KEYDOWN:
if event.key in (pygame.K_SPACE, pygame.K_w):
# add bullet
bullets.append(bullet.get_rect(center=player_rect.center))
# - updates (without draws) -
keys = pygame.key.get_pressed()
# move player
if keys[pygame.K_a] or keys[pygame.K_LEFT]:
player_rect.x -= 5
if player_rect.left < screen_rect.left:
player_rect.left = screen_rect.left
elif keys[pygame.K_d] or keys[pygame.K_RIGHT]:
player_rect.x += 5
if player_rect.right > screen_rect.right:
player_rect.right = screen_rect.right
# move bullets
for b in bullets:
if b.bottom > screen_rect.top:
b.y -= 1
# move aliens
switch_direction = False
for a in aliens:
if move_right:
a.x += 1
if a.right >= screen_rect.right:
switch_direction = True
else:
a.x -= 1
if a.left <= screen_rect.left:
switch_direction = True
if switch_direction:
move_right = not move_right
for a in aliens:
a.y += 5
# check collisions
temp_aliens = []
for a in aliens:
for b in bullets:
if b.colliderect(a):
bullets.remove(b)
break
else:
temp_aliens.append(a)
aliens = temp_aliens
# - draws (without updates) -
#screen.fill(BLACK)
screen.blit(background, (0,0))
for a in aliens:
screen.blit(alien, a)
for b in bullets:
screen.blit(bullet, b)
screen.blit(player, player_rect)
pygame.display.flip()
我以前的'bulletpos'可以删除'我'吗?尝试:当'i'被移除时退出'for j'循环;或者在删除之前测试'i'是否仍在'alienpos'中 – fredtantini
PyGame有特殊的功能来检查使用'pygame.Rect()'的冲突。它有'pygame.sprite.Group()'保留了一组对象,它可以检查冲突并自动删除元素。 – furas
在Python中,最好创建新列表并在for循环中添加要保留的元素,而不是从oryginal列表中删除元素。在'for-loop'之后,你指定了一个新的列表来取代oryginal列表。 – furas