无法在 Pygame 中检测到多个矩形冲突

Unable to detect multiple Rect Collisions in Pygame

我一直在从事一个简单的 Pygame 项目,该项目涉及在开放区域模拟运动传感器灯,并创建了多个送货员、吸烟者和平民的实例。当用户在一定距离内时,地面上的灯会亮起。我遇到的问题是,当 objects 与 driver 发生碰撞时,colliderect 根本没有触发(用 print 语句测试)。理想情况下,除了 driver 和吸烟者之外,所有平民都应该相互碰撞和反射。

这是我的虚拟原型的录音: LUmen Simulator

显示设置和距离功能

screen = width,height = 800,600
fps = 60 
cellsize = 50 
padding = 40 # create identations from the window 
rows = cols = (width - 50) // cellsize 
print(rows, cols) 

def euclid_dist(mX, mY, x, y): # distance to grid 
        dist = math.sqrt((mX - x)**2 + (mY - y)**2)

        if dist <= 80: 
            return True
        else: 
            return False 

objects

的实例化
class Cell_1: # sample of user object 
    def __init__(self):
        self.x = random.randrange(20, width-20) #x position
        self.y = random.randrange(20, height-20) #y position
        self.x_speed = 2
        self.y_speed = 2 

        self.image = char # pre-loaded img 
        self.image = pygame.transform.scale(self.image, (cellsize, cellsize+20))
        self.rect = pygame.Surface.get_rect(self.image, center= (self.x, self.y))

    def wander(self):
        self.x += self.x_speed 
        self.y += self.y_speed

        if self.x <= 30 or self.x >= width - 30:
            self.x_speed *= -1 

        elif self.y <= 30 or self.y >= height - 30:
            self.y_speed *= -1

    def draw(self): 
        surface.blit(self.image, (self.x, self.y))

class Cell_2: 
    def __init__(self):
        self.x = random.randrange(20, width-20) #x position
        self.y = random.randrange(20, height-20) #y position
        self.x_speed = 2
        self.y_speed = 2 

        self.image = char # pre-loaded img 
        self.image = pygame.transform.scale(self.image, (cellsize, cellsize+20))
        self.rect = pygame.Surface.get_rect(self.image, center= (self.x, self.y))

    def wander(self):
        self.x += self.x_speed 
        self.y += self.y_speed

        if self.x <= 30 or self.x >= width - 30:
            self.x_speed *= -1 

        elif self.y <= 30 or self.y >= height - 30:
            self.y_speed *= -1

    def draw(self): 
        surface.blit(self.image, (self.x, self.y))


class Driver: 
    # make driving linear 
    def __init__(self):
        self.x = random.randrange(20, width-20) #x position
        self.y = height - 20 #bottom of screen 
        self.y_speed = 12
        self.x_speed = 12

        self.image = char3
        self.image = pygame.transform.scale(self.image, (cellsize+20, cellsize+20))
        self.rect = pygame.Surface.get_rect(self.image, center = (self.x, self.y))

    def wander(self):
        if self.y <= 20: # height 
            self.y = height 
            self.x = random.randrange(20, width-20)

        else: 
            self.y -= self.y_speed

    def draw(self): 
        surface.blit(self.image, (self.x, self.y))

rects = [] 
cells_1 = []
for i in range(2): 
    cell = Cell_1()
    cells_1.append(cell)
    rects.append(cell) # for collision detection 

cells_2 = []
for i in range(2): 
    cell = Cell_2()
    cells_2.append(cell)
    rects.append(cell)

driver = Driver()

运行游戏

while running:
    warm_col = (255, random.randint(0, 255), 0)
    surface.fill(black)

    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            # upon closing the window with mouse 
            running = False 

    driver.wander()
    driver.draw() 
        
    for npc in cells_1: 
        npc.wander()
        npc.draw()

    for npc in cells_2: 
        npc.wander()
        npc.draw()

    for rectangle in rects:
        if (rectangle.rect.colliderect(driver.rect)): 
            rectangle.x_speed *= -1 
            rectangle.y_speed *= -1 
        
    (mX, mY) = pygame.mouse.get_pos()
    char1 = pygame.transform.scale(char1, (cellsize-10, cellsize+20)) 
    surface.blit(char1, (mX, mY))

    for row in range(rows): 
        for col in range(cols): 
            for i in rects: 
                    x = col * cellsize + padding
                    y = row * cellsize + padding 
                    within_dist = euclid_dist(mX, mY, x, y)
                    npc_within = euclid_dist(i.x, i.y, x, y) 

                    if within_dist == True or npc_within == True:
                        pygame.draw.circle(surface, warm_col, (x,y), 3) 


for row in range(rows): 
        for col in range(cols): 
            for i in cells_1: 
                    x = col * cellsize + padding
                    y = row * cellsize + padding 
                    within_dist = euclid_dist(mX, mY, x, y)
                    npc_within = euclid_dist(i.x, i.y, x, y) 

                    if within_dist == True or npc_within == True:
                        pygame.draw.circle(surface, warm_col, (x,y), 3) 

    for row in range(rows): 
        for col in range(cols): 
            for i in cells_2: 
                    x = col * cellsize + padding
                    y = row * cellsize + padding 
                    within_dist = euclid_dist(mX, mY, x, y)
                    npc_within = euclid_dist(i.x, i.y, x, y) 

                    if within_dist == True or npc_within == True:
                        pygame.draw.circle(surface, warm_col, (x,y), 3) 

    for row in range(rows): 
        for col in range(cols):  
                    x = col * cellsize + padding
                    y = row * cellsize + padding 
                    within_dist = euclid_dist(mX, mY, x, y)
                    npc_within = euclid_dist(driver.x, driver.y, x, y) 

                    if within_dist == True or npc_within == True:
                        pygame.draw.circle(surface, warm_col, (x,y), 3)   

              

    pygame.display.update() 
    pygame.time.Clock().tick(fps) 
    pygame.mouse.set_visible(False) 

pygame.quit()

我试过欧几里得距离,但它只适用于显示器的边缘 (gif) 我也尝试在此处实现碰撞逻辑 https://youtu.be/1_H7InPMjaY,但无济于事

我可以知道是否有更有效的方法来解决这个问题?我正在考虑使用 sprites 而不是 blit,但不确定是否会有任何不同。另外,我是 Pygame 的新手,所以任何帮助或建议都将不胜感激!

您必须在碰撞测试之前更新矩形的位置:

driver.rect.x = round(self.y)
driver.rect.y = round(self.y)
for rectangle in rects:
    rectangle.rect.x = round(rectangle.x)
    rectangle.rect.y = round(rectangle.y)
    if rectangle.rect.colliderect(driver.rect): 
        rectangle.x_speed *= -1 
        rectangle.y_speed *= -1