I want to create a simple Space Game but every time I want to shoot the alien, but I always get ValueError: list.remove(x): x not in list

Viewed 50

I am new in Python (3 months of experience) and I just started learning Pygame. I wanted to create a Space Game that shoot the aliens but I am getting "ValueError: list.remove(x): x not in list". I tried other solutions like creating a copy of list, using "while len(listname) <= num" but still getting the same error at the same place.

Here is the Player class:

class Player:
    def __init__(self, DISPLAYSURF):
        self.PLAYER      = pygame.image.load('SpaceRocket.png') #SpaceShip by dawnydawny from Pixabay
        self.XPLAYER     = (WINDOWWIDTH / 2) - 10
        self.YPLAYER     = WINDOWHEIGHT - 75
        self.FONT        = pygame.font.Font('freesansbold.ttf', 15)
        self.PBOX        = (self.XPLAYER, self.YPLAYER, 44, 77)
        self.DISPLAYSURF = DISPLAYSURF
        self.color       = WHITE
    
    
    def spaceMessage(self, message):
       self.message = message
       self.mesg    = self.FONT.render(self.message, True, self.color)
       self.DISPLAYSURF.blit(self.mesg, [50, WINDOWHEIGHT - 500])
    
   def showScore(self, score):
       self.score = score
       self.spaceMessage("SCORE: %s" % score)

Here is the UFO class:

class UFO:
    def __init__(self, XUFO, YUFO):
        self.XUFO = XUFO
        self.YUFO = YUFO
        self.UFO  = pygame.image.load('SpaceUFO.png') #Image by Mostafa Elturkey from Pixabay
        self.UBOX = (self.XUFO, self.YUFO, 95, 52)
    
    def makeUFO(self, DISPLAYSURF):
        self.DISPLAYSURF = DISPLAYSURF
        self.DISPLAYSURF.blit(self.UFO, [self.XUFO, self.YUFO])

Here is the main game loop:

SpaceUFO    = []
SpaceBullet = []
def runGame(Player):
    global FPSCLOCK, BACKGROUNDIMG, DISPLAYSURF, SpaceUFO

    DISPLAYSURF   = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
    BACKGROUNDIMG = pygame.image.load('SpaceBackground.jpg') # Image by Free-Photos from Pixabay 
    FPSCLOCK      = pygame.time.Clock()
    Player        = Player(DISPLAYSURF)
    SpaceKill     = 0
    SCORE         = 0
    BulletSound   = mixer.Sound('BulletSound.wav') # From https://www.freesoundeffects.com/
    pygame.display.set_caption('Space Fight by MadCoderErrr')
    mixer.music.load('SpaceSound.mp3') # Music: https://www.bensound.com
    mixer.music.play(-1)

    if SpaceKill > 0:
        SpaceKill += 1
    if SpaceKill > 10:
        SpaceKill = 0

    while True:
        DISPLAYSURF.blit(BACKGROUNDIMG, [0, 0])
    
        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            
        if len(SpaceUFO) < 5:
            SpaceUFO.append(UFO(round(random.randrange(0, WINDOWWIDTH - 20.0 ** 2) * 20.0) / 20.0, WINDOWHEIGHT - 570))
            print('making new aliens')
        
        for ufo in SpaceUFO.copy():
            ufo.makeUFO(DISPLAYSURF)
            ufo.YUFO += FPS / 4
        
        for ufo in SpaceUFO:
            if ufo.YUFO >= WINDOWHEIGHT:
                SpaceUFO.pop(SpaceUFO.index(ufo))
                print('Alien is gone')
            
        for bullet in SpaceBullet.copy():
            DISPLAYSURF.blit(bullet.SpaceBulletIMG, [bullet.bulletx, bullet.bullety])
            if bullet.bullety > 0:
                bullet.bullety -= FPS
            if bullet.bullety < 0:
                SpaceBullet.pop()
                print('Bullet is now gone!')
                
        if SpaceBullet:
            for b in SpaceBullet.copy():
                for u in SpaceUFO.copy():
                    if b.bullety < ufo.UBOX[1] + ufo.UBOX[3] and b.bullety > u.UBOX[1]:
                        if b.bulletx > u.UBOX[0] and b.bulletx < u.UBOX[0] + u.UBOX[2]:
                            SpaceUFO.remove(u)
                            SpaceBullet.remove(b)
                            SCORE += 1
                            print('You killed the alien')
            
        if event.type == KEYDOWN:
            if event.key == K_LEFT and not Player.XPLAYER <= 0:
                Player.XPLAYER -= FPS
            if event.key == K_RIGHT and Player.XPLAYER < WINDOWWIDTH - (FPS * 3):
                Player.XPLAYER += FPS
            if event.key == K_SPACE and SpaceKill < 10:
                if len(SpaceBullet) < 10:
                    SpaceBullet.append(Bullet(Player.XPLAYER, Player.YPLAYER))
                SpaceKill = 1
                BulletSound.play()
            
        Player.showScore(SCORE)
        DISPLAYSURF.blit(Player.PLAYER, [Player.XPLAYER, Player.YPLAYER])
        FPSCLOCK.tick(FPS)
        pygame.display.flip()
        pygame.display.update()
    
if __name__ == '__main__':
    runGame(Player)

This is the place where I always get an error:

    if SpaceBullet:
        for b in SpaceBullet.copy():
            for u in SpaceUFO.copy():
                if b.bullety < ufo.UBOX[1] + ufo.UBOX[3] and b.bullety > u.UBOX[1]:
                    if b.bulletx > u.UBOX[0] and b.bulletx < u.UBOX[0] + u.UBOX[2]:
                        SpaceUFO.remove(u)
                        SpaceBullet.remove(b)
                        SCORE += 1
                        print('You killed the alien')

This is the full traceback:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-1-80ff4a993e41> in <module>
    137 
    138 if __name__ == '__main__':
--> 139     runGame(Player)

<ipython-input-1-80ff4a993e41> in runGame(Player)
    115                         if b.bulletx > u.UBOX[0] and b.bulletx < u.UBOX[0] + u.UBOX[2]:
    116                             SpaceUFO.remove(u)
--> 117                             SpaceBullet.remove(b)
    118                             SCORE += 1
    119                             print('You killed the alien')

ValueError: list.remove(x): x not in list

Guys I am really clueless now, I've been coding this for almost 40 hrs but I am still struggling. Thank you guys in advance

1 Answers

The issue is seems to be cause, when multiple ufos are hit by one bullet. In this case b is tried to be removed multiple times. break the inner loop when a bullet is destroyed:

if SpaceBullet:
    for b in SpaceBullet.copy():
        for u in SpaceUFO.copy():
            if b.bullety < ufo.UBOX[1] + ufo.UBOX[3] and b.bullety > u.UBOX[1]:
                if b.bulletx > u.UBOX[0] and b.bulletx < u.UBOX[0] + u.UBOX[2]:
                    SpaceUFO.remove(u)
                    SpaceBullet.remove(b)
                    SCORE += 1
                    print('You killed the alien')
                    
                    break

I recommend to use pygame.Rect/collidepoint() for the collision test:

if SpaceBullet:
    for u in SpaceUFO.copy():
        u_rect = pygame.Rect(*u.UBOX)
        for b in SpaceBullet.copy():
            if u_rect.collidepoint(b.bulletx, b.bullety):
                SpaceUFO.remove(u)
                SpaceBullet.remove(b)
                SCORE += 1
                print('You killed the alien')
                    
                break

Note, the code can be simplified a lot by the use of pygame.sprite.Group, pygame.sprite.Sprite and pygame.sprite.Sprite.kill.

Related