为什么colliderect无法检测到我的碰撞

时间:2019-08-04 14:36:15

标签: python pygame

我对编码很陌生,正在通过重新创建旧的街机游戏来学习,在这里我正在制造太空侵略者,并且在大炮上显示了外星人,我可以发射大炮,并且目前正在尝试进行碰撞检测在子弹和与之打交道的外星人之间发生冲突,但是根本不起作用。

import pygame,sys,time
from pygame.locals import *


pygame.init()

windowwidth = 1000
windowheight = 700

windowsurface = pygame.display.set_mode((windowwidth,windowheight),0,32)
pygame.display.set_caption("SPACE INVADERS")


BLACK = (0,0,0)
WHITE = (255,255,255)


#
#OBJECTS
#


#Cannon Class
class theCannon:
    def __init__(self,left,bottom):

        self.left = left
        self.bottom = bottom


    def movecannonleft(self,left):
        self.left -= 6

    def movecannonright(self,left):
        self.left += 6

#End Cannon Class

##ALIEN STUFFS
#Alien Class
class Alien:
    def __init__(self,left,bottom):

        self.left = left
        self.bottom = bottom

#End Alien Class

#creates object aliens in arrays

#tr top row of aliens
trobj = []
trleft = 85
for i in range(1,12):
    trobj.append(Alien(trleft,80))
    trleft += 80
trobj.append(Alien(1100,80))#bug fixer alien

#mr1 second row of aliens
mr1obj = []         
mr1left = 85
for i in range(1,12):
    mr1obj.append(Alien(mr1left,80))
    mr1left += 80
mr1obj.append(Alien(1100,80))#bug fixer alien

#mr2 Third row
mr2obj = []
mr2left = 85
for i in range(1,12):
    mr2obj.append(Alien(mr2left,80))
    mr2left += 80
mr2obj.append(Alien(1100,80))#bug fixer alien

#br1 fourth row
br1obj = []
br1left = 85
for i in range(1,12):
    br1obj.append(Alien(br1left,80))
    br1left += 80
br1obj.append(Alien(1100,80))#bug fixer alien

#br2 fifth row
br2obj = []
br2left = 85
for i in range(1,12):
    br2obj.append(Alien(br2left,80))
    br2left += 80
br2obj.append(Alien(1100,80))#bug fixer alien



##END ALIEN STUFFS

#Bullet Class
activebulletx = 0
cannonactive = False

class Bullet:
    def __init__(self,top,left):

        self.top = top
        self.left = left

    def bullet_shooting(self,left):
        activebulletx = left
        self.left = left + 23
        self.top = 650

    def bullet_going(self,cannonactive):
        if cannonactive == True:
            self.top -= 6

    def bullet_top_hitting(self):
        if self.top < 0:
            self.top = -10000
            return False
        else:
            return True

#END BULLET CLASS


#
#END OBJECTS
#


left = 475
mycannonobj = theCannon(475,650)
bulletobj = Bullet(-10000,10000)

while True:

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    windowsurface.fill(BLACK)

    mycannon = pygame.Rect(mycannonobj.left,mycannonobj.bottom,50,25)
    pygame.draw.rect(windowsurface, WHITE, mycannon)

    bullet = pygame.Rect(bulletobj.left,bulletobj.top,5,20)
    pygame.draw.rect(windowsurface, WHITE, bullet)


    #moving cannon
    if pygame.key.get_pressed()[K_a] and mycannon.left > 0:
        mycannonobj.movecannonleft(mycannon.left)

    if pygame.key.get_pressed()[K_d] and mycannon.right < windowwidth:
        mycannonobj.movecannonright(mycannon.right)

    #player firing bullet
    if pygame.key.get_pressed()[K_w] and not cannonactive:
        cannonactive = True
        bulletobj.bullet_shooting(mycannon.left)

    cannonactive = bulletobj.bullet_top_hitting()
    bulletobj.bullet_going(cannonactive)


    #translates aliens into rects and puts onto the screen
    tr = []
    for i in range(0,12):
        tr.append(pygame.Rect(trobj[i].left,80,30,30))              
    for i in range(0,len(tr)):
        pygame.draw.rect(windowsurface, WHITE, tr[i])

    mr1 = []
    for i in range(0,12):
        mr1.append(pygame.Rect(mr1obj[i].left,150,30,30))
    for i in range(0,len(mr1)):
        pygame.draw.rect(windowsurface, WHITE, mr1[i])

    mr2 = []
    for i in range(0,12):
        mr2.append(pygame.Rect(mr2obj[i].left,220,30,30))
    for i in range(0,len(mr2)):
        pygame.draw.rect(windowsurface, WHITE, mr2[i])

    br1 = []
    for i in range(0,12):
        br1.append(pygame.Rect(br1obj[i].left,290,30,30))
    for i in range(0,len(br1)):
        pygame.draw.rect(windowsurface, WHITE, br1[i])

    br2 = []
    for i in range(0,12):
        br2.append(pygame.Rect(br2obj[i].left,360,30,30))
    for i in range(0,len(br2)):
        pygame.draw.rect(windowsurface, WHITE, br2[i])                 



    #hit detection for aliens and bullet

    for i in range(0,len(tr)-1):
        if bullet.colliderect(tr[i]):
            bullet.top = -10000
            cannonactive = False
            del tr[i]

    #screen updates
    pygame.display.update()
    time.sleep(0.02)

当玩家向外星人发射子弹时,它会直接穿过他们,包括应该检测到它的第一行。

1 个答案:

答案 0 :(得分:0)

您正在不断在主应用程序循环中重新创建矩形列表:

  
while True:

   # [...]

   tr = []
   for i in range(0,12):
       tr.append(pygame.Rect(trobj[i].left,80,30,30))

在循环之前创建一次矩形列表,并在循环中删除“命中”矩形。例如:

tr = []
for i in range(0,12):
    tr.append(pygame.Rect(trobj[i].left,80,30,30)) 

# [...]

while True:

    # [...]

    for i in range(0,len(tr)):
        pygame.draw.rect(windowsurface, WHITE, tr[i])

    for i in range(len(tr)-1, -1, -1): 
        if bullet.colliderect(tr[i]):
            bullet.top = -10000
            cannonactive = False
            del tr[i]

请注意,您必须以相反的顺序遍历矩形列表,否则,如果del tr[i]从列表中删除了一个元素,则将“超出范围”访问列表。
还要注意,rangestop自变量不包含在范围内。参见Ranges

或者,当遇到1个元素时,您可以break循环:

for i in range(len(tr)):
    if bullet.colliderect(tr[i]):
        bullet.top = -10000
        cannonactive = False
        del tr[i]
        break