Home > Net >  Change_layer() function pygame issue with removal from list
Change_layer() function pygame issue with removal from list

Time:09-13

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)
  • Related