I'm encountering an issue with attempting to use the change_layer() function for pygame where it raises an error message located in pygame's code stating:
Python\Python310\lib\site-packages\pygame\sprite.py", line 922, in change_layer
sprites.remove(sprite)
ValueError: list.remove(x): x not in list
I checked the code for pygame and found a comment stating that sprites must be added to the renderer for the function to work, but I'm not sure how that's done and if I've already done it with my code. Program I was working on for context (apologies for the code dump, but I'm so unsure what exactly I'm doing wrong that I don't know what is and isn't relevant to any possible solution:
import pygame
import os
from time import sleep
pygame.init()
clock = pygame.time.Clock()
FPS = 60
#if you see code that's been commented out, it's most likely just old debug code. You don't need to do anything about it.
global group
global customer
group = pygame.sprite.LayeredUpdates()
#makes screen and names it (name not necessary for function, but looks professional.)
screen = pygame.display.set_mode((819, 460))
pygame.display.set_caption("MCG: ascendancy")
#changes terminal pointer to the sprites folder so as to load the image files
os.chdir("C:\Program Files (x86)\Mason County Gas\sprites")
#list of possible sprites(TODO alter/move the while-true loop once more sprites for customer are implemented)
customerSprites = []
customerSprites.append(pygame.image.load("customerplaceholder.png"))
customerSprites.append(pygame.image.load("Customerplaceholder2.png"))
#creates sprites and determines their properties such as layer and position
class Hud(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("Hudplaceholder.png")
self.rect = self.image.get_rect(center=(posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class Health(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("Healthplaceholder.png")
self.rect = self.image.get_rect(center=(posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class Eye1(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("eyeplaceholder1.png")
self.rect = self.image.get_rect(center=(posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class Ammo(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("Ammoplaceholder.png")
self.rect = self.image.get_rect(center=(posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class Desk1(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("deskplaceholder_alt.png")
self.rect = self.image.get_rect(center=(posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class Interior(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("Interiorplaceholder.png")
self.rect = self.image.get_rect(center=(posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class DeskUnder(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("hideplaceholder.png")
self.rect = self.image.get_rect(center=(posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class Shelf(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("shelfplaceholder.png")
self.rect = self.image.get_rect(center=(posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class DrinksMachine(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("drinksplaceholder.png")
self.rect = self.image.get_rect(center=(posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class Gun(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("rifleplaceholder.png")
self.rect = self.image.get_rect(center = (posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
class Customer(pygame.sprite.Sprite):
def __init__(self, group, layer, posX, posY):
self.image = pygame.image.load("customerplaceholder.png")
self.rect = self.image.get_rect(center = (posX, posY))
self._layer = layer
pygame.sprite.Sprite.__init__(self, group)
def move(self, posX, posY):
self.rect.centerx = posX
self.rect.centery = posY
print(self.rect.centerx, self.rect.centery)
#the queue of customers/anomalies in the shop
queue = []
global queueObjectCount
queueObjectCount = 0
def spawnCustomer():
global queueObjectCount
if queueObjectCount <= 6:
global queueCustomer
queueCustomer = Customer(group, 0, 60, 100)
queue.append(queueCustomer)
queueObjectCount = 1
spawnCustomer()
#draws sprites onto the screen
group = pygame.sprite.LayeredUpdates()
Hud(group, 3, 740, 55)
Health(group, 3, 790, 135)
Health(group, 3, 740, 135)
Health(group, 3, 690, 135)
Ammo(group, 3, 795, 190)
Ammo(group, 3, 755, 190)
Ammo(group, 3, 715, 190)
Ammo(group, 3, 675, 190)
Eye1(group, 3, 790, 250)
Desk1(group, 2, 409, 230)
Interior(group, 1, 410, 180)
Customer(group, 0, 60, 100)
group.update()
group.draw(screen)
pygame.display.flip()
#runs the game and displays the sprites
run = True
group = pygame.sprite.LayeredUpdates()
global perspective
perspective = 1
while run:
for event in pygame.event.get():
# print(event)
# print(pygame.event.get())
# print(pygame.event.event_name)
pygame.event.pump()
if event.type == pygame.QUIT:
run = False
pygame.quit()
raise SystemExit
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
perspective = 1
if event.key == pygame.K_a:
perspective = 3
if event.key == pygame.K_s:
perspective = 4
if event.key == pygame.K_d:
perspective = 2
clock.tick()
# screen.fill((0,0,0))
# group.update()
# group.draw(screen)
# pygame.display.flip()
if perspective == 1:
screen.fill(0)
group = pygame.sprite.LayeredUpdates()
#displays contents of the queue in the appropriate place on screen
#print(queue)
for i, contents in enumerate(queue):
#print(i, ",", contents)
if type(contents) == Customer:
#print("do you copy?")
if i == 0:
#print("the customer should be drawn")
group.change_layer(queueCustomer, 1)
queueCustomer.rect.centerx = 360
queueCustomer.rect.centery = 150
screen.blit(queueCustomer.image, (queueCustomer.rect.centerx, queueCustomer.rect.centery))
#don't put a flip() here or the screen goes all wierd and flickery
if i == 1:
queueCustomer.rect.centerx = 160
queueCustomer.rect.centery = 50
screen.blit(queueCustomer.image, (queueCustomer.rect.centerx, queueCustomer.rect.centery))
if i == 2:
queueCustomer.rect.centerx = 260
queueCustomer.rect.centery = 50
screen.blit(queueCustomer.image, (queueCustomer.rect.centerx, queueCustomer.rect.centery))
if i == 3:
queueCustomer.rect.centerx = 360
queueCustomer.rect.centery = 50
screen.blit(queueCustomer.image, (queueCustomer.rect.centerx, queueCustomer.rect.centery))
if i == 4:
group.change_layer(queueCustomer, 1)
queueCustomer.rect.centerx = 360
queueCustomer.rect.centery = 150
screen.blit(queueCustomer.image, (queueCustomer.rect.centerx, queueCustomer.rect.centery))
#displays the environment and HUD
#print("the environment should be drawn")
Hud(group, 3, 740, 55)
Health(group, 3, 790, 135)
Health(group, 3, 740, 135)
Health(group, 3, 690, 135)
Ammo(group, 3, 795, 190)
Ammo(group, 3, 755, 190)
Ammo(group, 3, 715, 190)
Ammo(group, 3, 675, 190)
Eye1(group, 3, 790, 250)
Desk1(group, 2, 409, 230)
Interior(group, 1, 410, 180)
group.update()
group.draw(screen)
pygame.display.flip()
if perspective == 2:
screen.fill(0)
group = pygame.sprite.LayeredUpdates()
Hud(group, 3, 740, 55)
Health(group, 3, 790, 135)
Health(group, 3, 740, 135)
Health(group, 3, 690, 135)
Ammo(group, 3, 795, 190)
Ammo(group, 3, 755, 190)
Ammo(group, 3, 715, 190)
Ammo(group, 3, 675, 190)
Eye1(group, 3, 790, 250)
Shelf(group, 2, 409, 230)
group.update()
group.draw(screen)
pygame.display.flip()
if perspective == 3:
screen.fill(0)
group = pygame.sprite.LayeredUpdates()
Hud(group, 3, 740, 55)
Health(group, 3, 790, 135)
Health(group, 3, 740, 135)
Health(group, 3, 690, 135)
Ammo(group, 3, 795, 190)
Ammo(group, 3, 755, 190)
Ammo(group, 3, 715, 190)
Ammo(group, 3, 675, 190)
Eye1(group, 3, 790, 250)
DrinksMachine(group, 2, 409, 230)
group.update()
group.draw(screen)
pygame.display.flip()
if perspective == 4:
screen.fill(0)
group = pygame.sprite.LayeredUpdates()
customer = Customer(group, 0, 60, 100)
Hud(group, 4, 740, 55)
Health(group, 4, 790, 135)
Health(group, 4, 740, 135)
Health(group, 4, 690, 135)
Ammo(group, 4, 795, 190)
Ammo(group, 4, 755, 190)
Ammo(group, 4, 715, 190)
Ammo(group, 4, 675, 190)
Eye1(group, 4, 790, 250)
DeskUnder(group, 2, 409, 230)
Interior(group, 1, 410, 180)
Gun(group, 4, 220, 250)
group.update()
group.draw(screen)
pygame.display.flip()
# movement = 0
# while movement <= 800:
# customer.move(5, 0)
# screen.fill((0,0,0))
# group.update()
# group.draw(screen)
# pygame.display.flip()
# sleep(0.1)
# movement = 1
If someone could explain what I'm doing wrong and suggest a possible fix, that would be fantastic.
CodePudding user response:
Looks like you're trying to change the layer of a sprite that's not in the group. In your code, right before calling group.change_layer(queueCustomer, 1)
, you are reassigning group
to a empty LayeredUpdates
object:
# edited code snippet from your source
if perspective == 1:
screen.fill(0)
group = pygame.sprite.LayeredUpdates() # <- reasigned group to an empty object
for i, contents in enumerate(queue):
if type(contents) == Customer:
if i == 0:
group.change_layer(queueCustomer, 1) # <- 'queueCustomer' is not in group
...
To debug your code and make sure to not raise an exception while this happens, try using group.has(sprite)
to see if the sprite is in the group before trying to do anything with it, eg:
print(f"is customer in the group? {group.has(customer)}")
if group.has(customer):
group.change_layer(customer, 1)