Skip to content
Advertisement

Pygame collision checking lists of hit boxes against each other only checks the last box in the list

I am coding a game in pygame and my entity objects have attribute lists of hit boxes.

All the hit boxes are pygame.rect objects and when i have them drawn on the screen all of them show up but for some reason the objects only act like they collide if the last hit box in their list collides with the last hit box in the other objects list.

Here is the method I use for the check:

def collide_check(self, obj):
    self.update_hit_boxes()
    obj.update_hit_boxes()
    is_collide = False
    if self.can_collide and obj.can_collide:
        for box in self.hit_boxes:
            for obj_box in obj.hit_boxes:
                is_collide = box.colliderect(obj_box)
                if is_collide:
                    break
    else:
        is_collide = False
    return is_collide

Anyone have an idea what I’m doing wrong here or if this is even possible using only pygame.rect objects and pygame.rect.collide_rect?

Advertisement

Answer

I can’t test it but problem can be because break can exit only last/inner for-loop – so code still runs outer for-loop which can set again is_collide = False (because it runs is_collide = box.colliderect(obj_box)). And finally it gets is_collide = True only if last boxes collides.

You should check collision without assigning to variable and assign variable only inside if`

                if box.colliderect(obj_box):
                    is_collide = True
                    break

instead of

                is_collide = box.colliderect(obj_box)
                if is_collide:
                    break

Ot put both for-loops in separated function and use return True instead of break

def test(obj1, obj2):
    for box1 in obj1.hit_boxes:
        for obj2 in obj2.hit_boxes:
            if box1.colliderect(box2):
                return True
    return False

def collide_check(self, obj):
    self.update_hit_boxes()
    obj.update_hit_boxes()
    is_collide = False
    if self.can_collide and obj.can_collide:
        is_collide = test(self, obj)
    return is_collide

EDIT:

You could use return directly in original function

def collide_check(self, obj):
    self.update_hit_boxes()
    obj.update_hit_boxes()

    if self.can_collide and obj.can_collide:
        for box in self.hit_boxes:
            for obj_box in obj.hit_boxes:
                if box.colliderect(obj_box):
                    return True

    return False
Advertisement