简体   繁体   中英

pygame-How do I check if there is collision with any rect in an array?

I have an array of Box objects that each have a rect attribute. I'm trying to check if my player collides with any of the rects in the array. The way it's working now, the logic only works on the last element of the array, so my player will only collide with one of the rects and all the other ones he just walks over them. I think there might be a better way to check for collision with any of the rects, but here is what I have:

class Box:
def __init__(self, a, b, c, d):
    self.rect = pygame.Rect(a, b, c, d)

...

def detect_collisions(self, player_obj):
    for b in range(len(self.collision_boxes)):
        if pygame.Rect.colliderect(self.collision_boxes[b].rect, player_obj.top_rect):
            player_obj.can_move_up = False
        else:
            player_obj.can_move_up = True
        if pygame.Rect.colliderect(self.collision_boxes[b].rect, player_obj.bottom_rect):
            player_obj.can_move_down = False
        else:
            player_obj.can_move_down = True
        if pygame.Rect.colliderect(self.collision_boxes[b].rect, player_obj.left_rect):
            player_obj.can_move_left = False
        else:
            player_obj.can_move_left = True
        if pygame.Rect.colliderect(self.collision_boxes[b].rect, player_obj.right_rect):
            player_obj.can_move_right = False
        else:
            player_obj.can_move_right = True

Basically, the player has a rect on each edge, and if one of the edges collides with any of the other rects, it stops the player from moving in that direction. The array collision_boxes does contain all the box objects and not just the last one, I have checked it.

When I call the detect_collisions function, I do it like this:

    keys = pygame.key.get_pressed()

if keys[pygame.K_w]:  # check for keystrokes
    player.faceDirection = "U"
    if player.y_pos > current_map.map_bounds_upper:  # check bounds
        current_map.detect_collisions(player)
        if player.can_move_up:
            player.move_up()

Is there a better way to check every element in the array in this case? Where am I going wrong with this loop that causes it to only run the if statements on the last element in collision_boxes?

Every time the code is executed in the loop, all 4 states ( can_move_up , can_move_down , can_move_left , can_move_right ) are set. In each loop iteration, the results of the previous loop are overwritten. At the end only the results of the last run are set.

Set the status variables before the loop, but reset them inside the loop:

def detect_collisions(self, player_obj):

    player_obj.can_move_up = True
    player_obj.can_move_down = True
    player_obj.can_move_left = True
    player_obj.can_move_right = True

    for b in self.collision_boxes:
        if player_obj.top_rect.colliderect(b.rect):
            player_obj.can_move_up = False
        if player_obj.bottom_rect.colliderect(b.rect):
            player_obj.can_move_down = False
        if player_obj.left_rect.colliderect(b.rect):
            player_obj.can_move_left = False
        if player_obj.right_rect.colliderect(b.rect):
            player_obj.can_move_right = False

You can simplify your code by creating a list of pygame.Rect objects and using pygame.Rect.collidelist :

collidelist(list) -> index
Test whether the rectangle collides with any in a sequence of rectangles. The index of the first collision found is returned. If no collisions are found an index of -1 is returned.

def detect_collisions(self, player_obj):

    rect_list = [b.rect for b in self.collision_boxes]

    player_obj.can_move_up =  player_obj.top_rect.collidelist(rect_list) == -1
    player_obj.can_move_down = player_obj.bottom_rect.collidelist(rect_list) == -1
    player_obj.can_move_left = player_obj.left_rect.collidelist(rect_list) == -1
    player_obj.can_move_right = player_obj.right_rect.collidelist(rect_list) == -1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM