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.
JavaScript
x
14
14
1
import pygame
2
import random
3
import time
4
5
WIDTH, HEIGHT = (750, 600)
6
7
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
8
pygame.display.set_caption("Space İnvader Game")
9
BG_IMAGE = pygame.transform.scale(pygame.image.load("yeni_resim.jpg"), (WIDTH, HEIGHT))
10
CAPTION_IMAGE = pygame.image.load("spaceship.png")
11
ENEMY_IMAGE = pygame.image.load("enemy.png")
12
BULLET_IMAGE = pygame.image.load("bullet.png")
13
PLAYER_IMAGE = pygame.image.load("warship.png")
14
creating bullet class
JavaScript
1
58
58
1
class Bullet:
2
def __init__(self, x, y):
3
self.x = x
4
self.y = y
5
self.img = BULLET_IMAGE
6
self.mask = pygame.mask.from_surface(self.img)
7
self.vel = 8
8
self.hitbox = (self.x, self.y, 32,32)
9
10
def draw(self, window):
11
window.blit(self.img, (self.x, self.y))
12
self.hitbox = (self.x, self.y, 32, 32)
13
pygame.draw.rect(window,(0,0,255),self.hitbox,2)
14
15
def get_width(self):
16
return self.img.get_width()
17
18
def get_height(self):
19
return self.img.get_height()
20
21
def collide(self, obj1, obj2):
22
self.offset_x = obj2.x - obj1.x
23
self.offset_y = obj2.y - obj1.y
24
return obj1.mask.overlap(obj2.mask , (self.offset_x, self.offset_y)) != None
25
26
class Ship:
27
def __init__(self, x, y,width,height):
28
self.x = x
29
self.y = y
30
self.width = width
31
self.height = height
32
self.ship_img = None
33
34
35
def draw(self, window):
36
window.blit(self.ship_img, (self.x, self.y))
37
38
39
def get_width(self):
40
return self.ship_img.get_width()
41
42
def get_height(self):
43
return self.ship_img.get_height()
44
45
46
class Player(Ship):
47
48
def __init__(self, x, y,width,height):
49
super().__init__(x, y,width,height)
50
self.ship_img = PLAYER_IMAGE
51
self.mask = pygame.mask.from_surface(self.ship_img)
52
self.hitbox = (self.x, self.y, 64, 64)
53
54
def draw(self, window):
55
super().draw(window)
56
self.hitbox = (self.x , self.y , 64, 64)
57
pygame.draw.rect(window, (0, 0, 255), self.hitbox, 2)
58
creating enemy class and defining collide def
JavaScript
1
61
61
1
class Enemy():
2
3
def __init__(self, x, y):
4
self.x = x
5
self.y = y
6
self.ship_img = ENEMY_IMAGE
7
self.mask = pygame.mask.from_surface(self.ship_img)
8
self.enemy_vel = 4
9
self.hitbox = (self.x, self.y, 64, 64)
10
11
def draw(self, window):
12
self.hitbox = (self.x, self.y, 64, 64)
13
window.blit(self.ship_img,(self.x, self.y))
14
pygame.draw.rect(window, (255,0,0),self.hitbox,2)
15
16
def move(self,x,y):
17
self.x = x
18
self.y = y
19
self.x += self.enemy_vel
20
if self.x >= 686 or self.x <= 0:
21
self.enemy_vel *= -1
22
self.y += 5
23
24
def get_width(self):
25
return self.ship_img.get_width()
26
def get_height(self):
27
return self.ship_img.get_height()
28
29
def hit(self):
30
print("Hit")
31
32
def collide(self,obj1, obj2):
33
self.offset_x = obj2.x - obj1.x
34
self.offset_y = obj2.y - obj1.y
35
return obj1.mask.overlap(obj2.mask , (self.offset_x, self.offset_y)) != None
36
37
38
39
40
def main():
41
run = True
42
FPS = 60
43
clock = pygame.time.Clock()
44
bullets = []
45
enemies = []
46
player = Player(350, 500,64,64)
47
player_vel = 8
48
enemy_vel = 3
49
50
51
52
53
def redraw_window():
54
WIN.blit(BG_IMAGE,(0,0))
55
player.draw(WIN)
56
for bullet in bullets:
57
bullet.draw(WIN)
58
for enemy in enemies:
59
enemy.draw(WIN)
60
pygame.display.update()
61
calling collide definition in for enemy loop
JavaScript
1
43
43
1
while run:
2
clock.tick(FPS)
3
redraw_window()
4
5
6
if len(enemies) < 8:
7
enemies.append(Enemy(random.randint(0, 600), random.randint(0,200)))
8
9
for enemy in enemies:
10
enemy.move(enemy.x, enemy.y)
11
for bullet in bullets:
12
if bullet.collide(enemy,bullet):
13
enemies.pop(enemies.index(enemy))
14
bullets.pop(bullets.index(bullet))
15
16
17
18
19
for bullet in bullets:
20
if bullet.y < 600 and bullet.y > 0:
21
bullet.y -= bullet.vel
22
else:
23
bullets.pop(bullets.index(bullet))
24
25
26
keys = pygame.key.get_pressed()
27
if keys[pygame.K_RIGHT] and player.x + player_vel + player.get_width() < WIDTH:
28
player.x += player_vel
29
if keys[pygame.K_LEFT] and player.x - player_vel > 0:
30
player.x -= player_vel
31
if keys[pygame.K_SPACE]:
32
if len(bullets) < 10:
33
bullets.append(Bullet(round(player.x + 17),round(player.y)))
34
35
36
37
for event in pygame.event.get():
38
if event.type == pygame.QUIT:
39
run = False
40
41
42
main()
43
Then take this error after 6 or 7 time collision
JavaScript
1
10
10
1
C:Users191119AppDataLocalProgramsPythonPython38-32python.exe "C:/Users/191119/PycharmProjects/Pygame Projects2/AIGAMES.py"
2
pygame 1.9.6
3
Hello from the pygame community. https://www.pygame.org/contribute.html
4
Traceback (most recent call last):
5
File "C:/Users/191119/PycharmProjects/Pygame Projects2/AIGAMES.py", line 180, in <module>
6
main()
7
File "C:/Users/191119/PycharmProjects/Pygame Projects2/AIGAMES.py", line 151, in main
8
enemies.pop(enemies.index(enemy))
9
ValueError: <__main__.Enemy object at 0x07527868> is not in list
10
Advertisement
Answer
This is your problem:
JavaScript
1
7
1
for enemy in enemies:
2
enemy.move(enemy.x, enemy.y)
3
for bullet in bullets:
4
if bullet.collide(enemy,bullet):
5
enemies.pop(enemies.index(enemy))
6
bullets.pop(bullets.index(bullet))
7
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:
JavaScript
1
7
1
for enemy in enemies.copy():
2
enemy.move(enemy.x, enemy.y)
3
for bullet in bullets.copy():
4
if bullet.collide(enemy,bullet):
5
enemies.pop(enemies.index(enemy))
6
bullets.pop(bullets.index(bullet))
7
On a different note, it is not clear to me why you are doing this kind of operation:
JavaScript
1
2
1
bullets.pop(bullets.index(bullet))
2
instead of using remove()
like this:
JavaScript
1
2
1
bullets.remove(bullet)
2