首页 > 解决方案 > 为什么colliderect没有检测到我的碰撞

问题描述

我对编码很陌生,并且正在通过重新创建旧的街机游戏来学习,在这里我正在制作太空入侵者,并且我在屏幕上有外星人与大炮,我可以发射大炮,目前正在尝试检测子弹之间的碰撞和外星人一起使用colliderect,但它根本不起作用。

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)

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

标签: pythonpygame

解决方案


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

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]
进一步注意, 的stop参数range不包括在范围内。请参阅范围

或者,您可以break在命中 1 个元素时循环:

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

推荐阅读