We want to destroy the wall if the bullet hits it. To detect a hit, we can use the collidelist function on the bullet, similar to what we previously did with the tank. Since we have multiple bullets in a list, we will need to go through every bullet using a for loop.
for bullet in bullets: wall_index = bullet.collidelist(walls)
If wall_index is -1, that means that the bullet didn't hit any walls. Else, wall_index will contain the index of the wall section that the bullet hit. We can then delete that wall section using del.
for bullet in bullets: wall_index = bullet.collidelist(walls) del walls[wall_index]
The del command tells python to delete walls[wall_index] from the walls list. Make sure you understand how it works.
animals = ['cat', 'dog', 'monkey', 'elephant'] print(animals) del animals print(animals)
Now everytime you fire a bullet, it will pass through all the walls, destroying every wall section that it touches. That's probably not what you want! Let's make the bullet disappear too when it hits a wall. Another way or removing an item from a list is to use the remove function.
for bullet in bullets: wall_index = bullet.collidelist(walls) del walls[wall_index] bullets.remove(bullet)
Just like del, the remove function will remove an item from a list. The difference is that del requires a list with an index, while remove expects the value of the item to be removed.
animals = ['cat', 'dog', 'monkey', 'elephant'] print(animals) animals.remove('monkey') print(animals)
Now everytime your bullet hits a wall, both the bullet and the wall will disappear.
Reaching the edge
There is one more condition for removing the bullet; and that's when it reaches the edge of the screen.
if bullet.x < 0 or bullet.x > 800 or bullet.y < 0 or bullet.y > 600: bullets.remove(bullet)
Can you figure out where to insert this piece of code? Try it out!
At this point, your code should look like this...
import pgzrun import random WIDTH=800 HEIGHT=600 tank = Actor('tank_blue') tank.y = 575 tank.x = 400 tank.angle = 90 background = Actor('grass') walls =  for x in range(16): for y in range(10): if random.randint(0, 100) < 50: wall = Actor('wall') wall.x = x * 50 + 25 wall.y = y * 50 + 25 + 50 walls.append(wall) bullets =  bullet_holdoff = 0 def update(): global bullet_holdoff # This part is for the tank original_x = tank.x original_y = tank.y if keyboard.left: tank.x = tank.x - 2 tank.angle = 180 elif keyboard.right: tank.x = tank.x + 2 tank.angle = 0 elif keyboard.up: tank.y = tank.y - 2 tank.angle = 90 elif keyboard.down: tank.y = tank.y + 2 tank.angle = 270 if tank.collidelist(walls) != -1: tank.x = original_x tank.y = original_y if tank.x < 0 or tank.x > 800 or tank.y < 0 or tank.y > 600: tank.x = original_x tank.y = original_y # This part is for the bullet if bullet_holdoff == 0: if keyboard.space: bullet = Actor('bulletblue2') bullet.angle = tank.angle bullet.x = tank.x bullet.y = tank.y bullets.append(bullet) bullet_holdoff = 100 else: bullet_holdoff = bullet_holdoff - 1 for bullet in bullets: if bullet.angle == 0: bullet.x = bullet.x + 5 elif bullet.angle == 90: bullet.y = bullet.y - 5 elif bullet.angle == 180: bullet.x = bullet.x - 5 elif bullet.angle == 270: bullet.y = bullet.y + 5 for bullet in bullets: wall_index = bullet.collidelist(walls) if wall_index != -1: del walls[wall_index] bullets.remove(bullet) if bullet.x < 0 or bullet.x > 800 or bullet.y < 0 or bullet.y > 600: bullets.remove(bullet) def draw(): screen.fill((0,0,0)) background.draw() tank.draw() for bullet in bullets: bullet.draw() for wall in walls: wall.draw() pgzrun.go() # Must be last line
What happens if we don't remove the bullet when it reaches the edge?
Nothing much. The bullet will just keep flying forever outside of the screen. If you have a lot of bullets, it may eventually slow down your game, but it will likely require many thousands of bullets before that becomes noticeable.