python collision recursion issue

Started by
2 comments, last by kingpinzs 9 years, 11 months ago

    def touching(self, bubble, bubbles):
        for bubble1 in bubbles:
            bubble_old = bubble1
            if self.color == bubble_old.color and dist(bubble.pos, bubble_old.pos) <= 2 * BUBBLE_RADIUS:
                bubbles.remove(bubble_old)
                self.touching(bubble1, bubbles)
The error occurs when there are two rows right next to each that need to be removed.

for example like this
x x x x x
x O O O x
x x O O x
x x O x x
O <-current ball

Traceback (most recent call last):
File "main.py", line 140, in draw
if a_bubble.remove_matching(stuck_bubbles):
File "main.py", line 72, in remove_matching
self.touching(bubble_old, bubbles)
File "main.py", line 81, in touching
self.touching(bubble1, bubbles)
File "main.py", line 80, in touching
bubbles.remove(bubble_old)
KeyError: <__main__.Bubble instance at 0x192c878>

Advertisement

I'm struggling to see how you got a KeyError for this, unless you're doing something exotic ( in which case I'll need more code ).

Anyway, instead looping through a list and remove elements in the for loop, you should instead try one of the below:

  • Loop through a copy of the list of bubbles, removing from them from the original list ( for bubble1 in bubbles[:]: )
  • Loop through the list using an iterator ( for bubble1 in iter(bubbles): )

Also, you don't need to set bubble_old = bubble1. When you remove old_bubble from the list, you still hold the reference to it ( old_bubble is referenced to bubble1 ).


def touching(self, bubble, bubbles):
    for bubble1 in bubbles[:]:
        if self.color == bubble_old.color and dist(bubble.pos, bubble1.pos) <= 2 * BUBBLE_RADIUS:
            bubbles.remove(bubble1)
            self.touching(bubble1, bubbles)


    def remove_matching(self, bubbles):
        bubble_old = []
        for bubble in list(bubbles):
            if self.color == bubble.color and self.collide(bubble):
                bubble_old = bubble
                bubbles.remove(bubble)
                self.touching(bubble_old, bubbles)
                return True
        return False

this is the method that calls it.

The code works when the bubbles are lined up like this

x O x

x O x

x O x

O <-current ball

x O x

x O x

O O O

O <-current ball

the issue happens with anything like this

O O

O O

O <-current ball

I have also tried this


  def touching(self, bubble, bubbles):
        for bubble1 in list(bubbles):
            if self.color == bubble1.color and dist(bubble.pos, bubble1.pos) <= 2 * BUBBLE_RADIUS:
                bubbles.remove(bubble_old)
                self.touching(bubble1, bubbles)

I got the same error

and this gets this error RuntimeError: Set changed size during iteration


    def touching(self, bubble, bubbles):
        for bubble1 in iter(bubbles):
            if self.color == bubble1.color and dist(bubble.pos, bubble1.pos) <= 2 * BUBBLE_RADIUS:
                bubbles.remove(bubble1)
                self.touching(bubble1, bubbles)

I changed bubbles.remove(bubble1) to bubbles.discard(bubble1) and I no longer get the error. Thanks every one for taking the time to read my post.

This topic is closed to new replies.

Advertisement