解决循环中修改列表时Bubble碰撞后不消失的问题

37 阅读2分钟

在使用Python编写碰撞检测算法时,遇到一个问题,即当一个气球与一个气泡发生碰撞时,气泡并没有消失。在检查碰撞的代码块中,有以下代码:

huake_00152_.jpg

def check(balloon, bubbles, window):
    for bubble in bubbles:
       collide = balloonBubbleCollide(balloon, bubble)
       if collide == True:
            bubbles.remove(bubble)

当气泡与气球发生碰撞时,就会调用bubbles.remove(bubble)来删除该气泡。然而,这会导致一个问题,即在循环中修改列表。当列表正在被迭代时,修改列表的内容可能会导致意想不到的结果,甚至引发错误。

  1. 解决方案 为了解决这个问题,可以使用以下代码:
def check(balloon, bubbles, window):
    bubbles[:] = [bubble for bubble in bubbles
                  if not baloonBubbleCollide(balloon, bubble)]

这段代码使用列表推导式创建了一个新的气泡列表,其中只包含没有与气球发生碰撞的气泡。然后,使用[:]运算符将新的气泡列表赋值给bubbles列表。这样就避免了在循环中修改列表的问题。

以下是一个代码示例,演示了如何使用该解决方案:

import math

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def getX(self):
        return self.x

    def getY(self):
        return self.y

class Circle:
    def __init__(self, center, radius):
        self.center = center
        self.radius = radius

    def getCenter(self):
        return self.center

    def getRadius(self):
        return self.radius

def getDistance(point1, point2):
    a = point1.getX()
    b = point2.getX()
    c = point1.getY()
    d = point2.getY()
    distance = math.sqrt((b - a) ** 2 + ((d - c) ** 2))
    return distance

def balloonBubbleCollide(balloon, bubble):
    point1 = balloon.getCenter()
    point2 = bubble.getCenter()
    distance = getDistance(point1, point2)
    if distance <= 30:
        return True

def check(balloon, bubbles, window):
    bubbles[:] = [bubble for bubble in bubbles
                  if not balloonBubbleCollide(balloon, bubble)]

def main():
    balloon = Circle(Point(0, 0), 50)
    bubbles = [Circle(Point(100, 100), 10), Circle(Point(200, 200), 10),
               Circle(Point(300, 300), 10)]

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        check(balloon, bubbles, window)

        window.fill((255, 255, 255))
        pygame.draw.circle(window, (0, 0, 255),
                           (int(balloon.getCenter().getX()),
                            int(balloon.getCenter().getY())),
                           balloon.getRadius())
        for bubble in bubbles:
            pygame.draw.circle(window, (0, 255, 0),
                               (int(bubble.getCenter().getX()),
                                int(bubble.getCenter().getY())),
                               bubble.getRadius())

        pygame.display.update()

if __name__ == "__main__":
    main()

在上面的代码中,我们定义了一个Point类来表示点,一个Circle类来表示圆,以及一些函数来计算圆心之间的距离和检查两个圆是否发生碰撞。然后,我们在main函数中创建了一个气球和一些气泡,并在游戏循环中不断检查气球和气泡之间的碰撞,并删除发生碰撞的气泡。

通过使用列表推导式来创建新的气泡列表,我们避免了在循环中修改列表的问题,确保了碰撞检测算法能够正确地工作。