pygame-如何检查是否与数组中的任何矩形发生冲突?

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

我有一个 Box 对象数组,每个对象都有一个 rect 属性。我正在尝试检查我的播放器是否与阵列中的任何矩形发生碰撞。它现在的工作方式是,逻辑仅适用于数组的最后一个元素,因此我的玩家只会与其中一个矩形和他刚刚走过的所有其他矩形发生碰撞。我认为可能有更好的方法来检查与任何矩形的碰撞,但这是我所拥有的:

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

基本上,玩家在每条边上都有一个矩形,如果其中一条边与任何其他矩形发生碰撞,它会阻止玩家朝那个方向移动。数组 collision_boxes 确实包含所有框对象,而不仅仅是最后一个,我已经检查过了。

当我调用 detect_collisions 函数时,我是这样操作的:

    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()

在这种情况下,是否有更好的方法来检查数组中的每个元素?这个循环哪里出错了,导致它只 运行 collision_boxes 中最后一个元素的 if 语句?

每次在循环中执行代码时,都会设置所有4种状态(can_move_upcan_move_down can_move_leftcan_move_right )。在每次循环迭代中,前一个循环的结果都会被覆盖。最后只设置最后 运行 的结果。

在循环前设置状态变量,但在循环内重置它们:

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

您可以通过创建 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