Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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?

>Solution :

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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading