I’m attempting to create a Missile Command clone to challenge/expand my Python and Pygame skills and knowledge. Below is the code for the game so far (it’s rudimentary, I’m a beginner):
import math
import pygame
class Missile:
def __init__(self, surface):
self.surface = surface
self.missileList = []
self.color = (0, 255, 0)
def draw(self):
if len(self.missileList) > 0:
self.missileList.sort()
for i in range(0, len(self.missileList)):
if self.missileList[i][1] < self.missileList[i][4]:
self.missileList.pop(i)
else:
self.update(i)
self.surface.set_at((int(self.missileList[i][0]), int(self.missileList[i][1])), self.color)
def update(self, i):
self.missileList[i][0] -= self.missileList[i][3] * math.cos(self.missileList[i][2])
self.missileList[i][1] -= self.missileList[i][3] * math.sin(self.missileList[i][2])
width = 640
height = 480
BGCOLOR = (0, 0, 0)
mousex = 0
mousey = 0
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
startx = int(width / 2)
starty = height - 10
speed = 2
missile = Missile(screen)
running = True
while running:
screen.fill(BGCOLOR)
missile.draw()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
elif event.type == pygame.MOUSEMOTION:
mousex, mousey = event.pos
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
endx = mousex
endy = mousey
trajectory = math.atan2(height - endy, (width / 2) - endx)
missile.missileList += [[startx, starty, trajectory, speed, endy]]
pygame.display.flip()
clock.tick(75)
So each time I click the mouse button, missile.missileList is appended with all the information that is needed to get the ‘missile’ from start to finish. When a missile reaches its endpoint then those list entries are deleted. The problem is, this throws off the list indices thereafter and throws an error (list index out of range) if there is another missile being tracked. I thought sorting the list at the beginning of each draw() call would help, but it didn’t. Any ideas?
You’re modifying a list while iterating it, which is usually a mistake. In this case, the simplest way to make the code work is by iterating backwards:
That works because you only ever delete the current item in the loop – when you iterate backwards, deleting the current item only affects the indices of those items you’ve already seen.