2016-11-24 127 views
-1

我目前正在嘗試使用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上這個問題類似的問題,但沒有的建議一直是任何幫助很大。如果有任何更多的信息,你都需要我會很樂意發表評論。提前致謝!

+0

我以前的'bulletpos'可以刪除'我'嗎?嘗試:當'i'被移除時退出'for j'循環;或者在刪除之前測試'i'是否仍在'alienpos'中 – fredtantini

+0

PyGame有特殊的功能來檢查使用'pygame.Rect()'的衝突。它有'pygame.sprite.Group()'保留了一組對象,它可以檢查衝突並自動刪除元素。 – furas

+0

在Python中,最好創建新列表並在for循環中添加要保留的元素,而不是從oryginal列表中刪除元素。在'for-loop'之後,你指定了一個新的列表來取代oryginal列表。 – furas

回答

0

問題是因爲你從列表中刪除alien但後來你還檢查了這alien與其他bulletsbullet可能與此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()具有性能leftrighttopbottomcenter等,所以它更容易比較的位置 - 在屏幕上即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()