# \[SOLVED\] Py.processing bullet and enemy collision

**URL:** <https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327>\
**Category:** Processing.py\
**Created:** [February 12, 2019, 5:12pm UTC](https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327 "2019-02-12T17:12:42Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![warsoldier011](https://avatars.discourse-cdn.com/v4/letter/w/a6a055/32.png) [@warsoldier011](https://discourse.processing.org/u/warsoldier011)\
**Post date:** [February 12, 2019, 5:12pm UTC](https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327/1 "2019-02-12T17:12:43Z")

</div>

Hello there I am currently dealing with a bullet and enemy collision problem. I’m trying to kill both the enemy and the bullet and remove them from the screen, when they intersect each other. It works once and then I receive the error: “ValueError: list.index(x): x not in list on line 54 in main.py”. If someone could better enhance my code or tell me what I’m doing wrong. That would be much appreciated, thank you. Here is my code: [https://trinket.io/python/1c73517ac9](https://trinket.io/python/1c73517ac9)

I’m know the problem is here:

```auto
for e in enemies: #Iterate through the list of enemies
    e.display() 
    e.goToTarget(myPlayer.xpos, myPlayer.ypos) 
    for l in lasers:
      if l.collision(e.xpos, e.ypos, e.r):
        lasers.remove(l)
        enemies.remove(e) # "ValueError: list.index(x): x not in list on line 54 in main.py"
    if myPlayer.collision(e.xpos, e.ypos, e.r):
      enemies.remove(e)
####################

```

---

<div class="post-metadata">

**Author:** ![solub](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/solub/32/333_2.png) [@solub](https://discourse.processing.org/u/solub)\
**Post date:** [February 12, 2019, 6:45pm UTC](https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327/2 "2019-02-12T18:45:21Z")

</div>

Hi @warsoldier011,

You just need to add `break` at the end of your double `for` loop to terminate it. Otherwise the code keeps calling `remove` for every iteration.

```auto
for e in enemies: #Iterate through the list of enemies
    e.display() 
    e.goToTarget(myPlayer.xpos, myPlayer.ypos) 
    for l in lasers:
      if l.collision(e.xpos, e.ypos, e.r): 
          del lasers[lasers.index(l)]
          del enemies[enemies.index(e)]
          break

```

---

<div class="post-metadata">

**Author:** ![warsoldier011](https://avatars.discourse-cdn.com/v4/letter/w/a6a055/32.png) [@warsoldier011](https://discourse.processing.org/u/warsoldier011)\
**Post date:** [February 12, 2019, 8:33pm UTC](https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327/3 "2019-02-12T20:33:56Z")

</div>

Thank you very much. This bug has been stopping me in my progress.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [February 13, 2019, 9:04am UTC](https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327/4 "2019-02-13T09:04:03Z")

</div>

@solub, your solution is buggy! 🐛

When we delete an item from a list, all elements w/ a higher index than the deleted item got their indices subtracted by 1! 🧐

They’re left-shifted, and therefore, the next iteration skips an item; which now got the same index as the just deleted item. ⬅

You can see that bug in this sample loop below: 👁 :

```auto
nums = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for n in nums:
    print n
    nums.remove(n)
print nums # [1, 3, 5, 7, 9] 

```

The code above was supposed to remove all items from the list. But accomplished only half of it! 🤪

There are some techniques to pull that out though. 💡

In Java, my favorite approach is to simply traverse the list backwards instead. ☕

Python got **reversed()**, which returns a backwards iterator for a sequence. 🐍

```auto
nums = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for n in reversed(nums):
    print n
    nums.remove(n)
print nums # [] 

```

Now it’s finally worked! All items got backwards removed w/o any errors! 🥳

However, **remove()** ( and also **index()** ) is a slow method, given it’s gotta search the whole list for the target item. 🐌

A better approach is to use `del`, since it removes an item by its index. 🗂

For that, we’re gonna need to use **enumerate()** and also turn it into a sequence before calling **reversed()**: 🔙

```auto
nums = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i, n in reversed(tuple(enumerate(nums))):
    print i, n
    del nums[i]
print nums # [] 

```

Here’s @warsoldier011’s excerpt adapted to use a backwards loop w/ `del`: 👼

```python
for i, e in reversed(tuple(enumerate(enemies))):
    e.display()
    e.goToTarget(myPlayer.xpos, myPlayer.ypos)

    # for j, l in reversed(tuple(enumerate(lasers))): # no need w/ break
    for j, l in enumerate(lasers):
        if l.collision(e.xpos, e.ypos, e.r):
            del lasers[j]
            del enemies[i]
            break

        l.display()

```

As a bonus, here’s a more advanced performant example, which replaces the item being removed w/ its list’s tail element; so there’s no index left-shifting at all: 🤑

```python
for i in range(len(enemies) - 1, -1, -1):
    e = enemies[i]

    e.display()
    e.goToTarget(myPlayer.xpos, myPlayer.ypos)

    # for j in range(len(lasers) - 1, -1, -1): # no need to be reversed w/ break
    for j in range(len(lasers)):
        l = lasers[j]

        if l.collision(e.xpos, e.ypos, e.r):
            tail = lasers.pop()
            if tail is not l: lasers[j] = tail

            tail = enemies.pop()
            if tail is not e: enemies[i] = tail

            break

        l.display()

```

---

<div class="post-metadata">

**Author:** ![solub](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/solub/32/333_2.png) [@solub](https://discourse.processing.org/u/solub)\
**Post date:** [February 13, 2019, 1:45pm UTC](https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327/5 "2019-02-13T13:45:09Z")

</div>

Thanks @GoToLoop, really like the `reversed` - `tuple` - `enumerate` combo.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [February 13, 2019, 5:13pm UTC](https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327/6 "2019-02-13T17:13:16Z")

</div>

> [@solub](#):
>
> … really like the `reversed` - `tuple` - `enumerate` combo.

We can also use **list()** in place of **tuple()**. 😉

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [February 13, 2019, 7:52pm UTC](https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327/7 "2019-02-13T19:52:13Z")

</div>

Just came to my mind: 🧠

Given the inner loop is interrupted by `break`, got no need for it to be **reversed()** as the outer loop. 🤦‍♂️

So we can replace: 💱  
`for j, l in reversed(tuple(enumerate(lasers))):`  
w/ just: 🙃  
`for j, l in enumerate(lasers):`

---

<div class="post-metadata">

**Author:** ![warsoldier011](https://avatars.discourse-cdn.com/v4/letter/w/a6a055/32.png) [@warsoldier011](https://discourse.processing.org/u/warsoldier011)\
**Post date:** [February 14, 2019, 12:54pm UTC](https://discourse.processing.org/t/solved-py-processing-bullet-and-enemy-collision/8327/8 "2019-02-14T12:54:45Z")

</div>

@GoToLoop Thank you very much for sharing your knowledge. The way you gave examples and showcased the code. Truly helpful, thanks once again.
