Skip to content
Advertisement

ValueError: is not in list

I trying to make spaceship game from using pygame. Just simple game what warship shoot bullet and collide enemies. But when I play my game, after 6 or 7 collisions I get below error.

import pygame
import random
import time

WIDTH, HEIGHT = (750, 600)

WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Space İnvader Game")
BG_IMAGE = pygame.transform.scale(pygame.image.load("yeni_resim.jpg"), (WIDTH, HEIGHT))
CAPTION_IMAGE = pygame.image.load("spaceship.png")
ENEMY_IMAGE = pygame.image.load("enemy.png")
BULLET_IMAGE = pygame.image.load("bullet.png")
PLAYER_IMAGE = pygame.image.load("warship.png")

creating bullet class

class Bullet:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.img = BULLET_IMAGE
        self.mask = pygame.mask.from_surface(self.img)
        self.vel = 8
        self.hitbox = (self.x, self.y, 32,32)

    def draw(self, window):
        window.blit(self.img, (self.x, self.y))
        self.hitbox = (self.x, self.y, 32, 32)
        pygame.draw.rect(window,(0,0,255),self.hitbox,2)

    def get_width(self):
        return self.img.get_width()

    def get_height(self):
        return self.img.get_height()

    def collide(self, obj1, obj2):
        self.offset_x = obj2.x - obj1.x
        self.offset_y = obj2.y - obj1.y
        return obj1.mask.overlap(obj2.mask , (self.offset_x, self.offset_y)) != None

class Ship:
    def __init__(self, x, y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.ship_img = None


    def draw(self, window):
        window.blit(self.ship_img, (self.x, self.y))


    def get_width(self):
        return self.ship_img.get_width()

    def get_height(self):
        return self.ship_img.get_height()


class Player(Ship):

    def __init__(self, x, y,width,height):
        super().__init__(x, y,width,height)
        self.ship_img = PLAYER_IMAGE
        self.mask = pygame.mask.from_surface(self.ship_img)
        self.hitbox = (self.x, self.y, 64, 64)

    def draw(self, window):
        super().draw(window)
        self.hitbox = (self.x , self.y , 64, 64)
        pygame.draw.rect(window, (0, 0, 255), self.hitbox, 2)

creating enemy class and defining collide def

class Enemy():

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.ship_img = ENEMY_IMAGE
        self.mask = pygame.mask.from_surface(self.ship_img)
        self.enemy_vel = 4
        self.hitbox = (self.x, self.y, 64, 64)

    def draw(self, window):
        self.hitbox = (self.x, self.y, 64, 64)
        window.blit(self.ship_img,(self.x, self.y))
        pygame.draw.rect(window, (255,0,0),self.hitbox,2)

    def move(self,x,y):
        self.x = x
        self.y = y
        self.x += self.enemy_vel
        if self.x >= 686 or self.x <= 0:
            self.enemy_vel *= -1
            self.y += 5

    def get_width(self):
        return self.ship_img.get_width()
    def get_height(self):
        return self.ship_img.get_height()

    def hit(self):
        print("Hit")

    def collide(self,obj1, obj2):
        self.offset_x = obj2.x - obj1.x
        self.offset_y = obj2.y - obj1.y
        return obj1.mask.overlap(obj2.mask , (self.offset_x, self.offset_y)) != None




def main():
    run = True
    FPS = 60
    clock = pygame.time.Clock()
    bullets = []
    enemies = []
    player = Player(350, 500,64,64)
    player_vel = 8
    enemy_vel = 3




    def redraw_window():
        WIN.blit(BG_IMAGE,(0,0))
        player.draw(WIN)
        for bullet in bullets:
            bullet.draw(WIN)
        for enemy in enemies:
            enemy.draw(WIN)
        pygame.display.update()

calling collide definition in for enemy loop

    while run:
        clock.tick(FPS)
        redraw_window()


        if len(enemies) < 8:
            enemies.append(Enemy(random.randint(0, 600), random.randint(0,200)))

        for enemy in enemies:
            enemy.move(enemy.x, enemy.y)
            for bullet in bullets:
                if bullet.collide(enemy,bullet):
                    enemies.pop(enemies.index(enemy))
                    bullets.pop(bullets.index(bullet))




        for bullet in bullets:
            if bullet.y < 600 and bullet.y > 0:
                bullet.y -= bullet.vel
            else:
                bullets.pop(bullets.index(bullet))


        keys = pygame.key.get_pressed()
        if keys[pygame.K_RIGHT] and player.x + player_vel + player.get_width() < WIDTH:
            player.x += player_vel
        if keys[pygame.K_LEFT] and player.x - player_vel > 0:
            player.x -= player_vel
        if keys[pygame.K_SPACE]:
            if len(bullets) < 10:
                bullets.append(Bullet(round(player.x + 17),round(player.y)))



        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False


main()

Then take this error after 6 or 7 time collision

C:Users191119AppDataLocalProgramsPythonPython38-32python.exe "C:/Users/191119/PycharmProjects/Pygame Projects2/AIGAMES.py"
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "C:/Users/191119/PycharmProjects/Pygame Projects2/AIGAMES.py", line 180, in <module>
    main()
  File "C:/Users/191119/PycharmProjects/Pygame Projects2/AIGAMES.py", line 151, in main
    enemies.pop(enemies.index(enemy))
ValueError: <__main__.Enemy object at 0x07527868> is not in list

Advertisement

Answer

This is your problem:

        for enemy in enemies:
            enemy.move(enemy.x, enemy.y)
            for bullet in bullets:
                if bullet.collide(enemy,bullet):
                    enemies.pop(enemies.index(enemy))
                    bullets.pop(bullets.index(bullet))

You are iterating over the lists and deleting elements from the lists while you are still going through them. That is not something that you are allowed to do.

Try iterating through a copy of the lists and deleting from the originals. Something like this:

        for enemy in enemies.copy():
            enemy.move(enemy.x, enemy.y)
            for bullet in bullets.copy():
                if bullet.collide(enemy,bullet):
                    enemies.pop(enemies.index(enemy))
                    bullets.pop(bullets.index(bullet))

On a different note, it is not clear to me why you are doing this kind of operation:

    bullets.pop(bullets.index(bullet))

instead of using remove() like this:

    bullets.remove(bullet)
Advertisement