Why isn't pygame rendering all my sprites?

Viewed 128

I'm trying to follow this tutorial to learn pygame. I'm to the point where I'm trying to spawn the enemy objects, but I think I've made a mistake, because nothing is displaying.

class Player(pygame.sprite.Sprite):
        def __init__(self):
            super(Player, self).__init__()
            self.surf = pygame.Surface((75,25))
            self.surf.fill((0, 0,0))
            self.rect = self.surf.get_rect()

           #Moves sprite based on keypresses(removed for clarity)
class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super(Enemy, self).__init__()
        self.surf = pygame.Surface((20,10))
        self.surf.fill((0,0,0))
        self.rect = self.surf.get_rect(
            center = (
            random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
            random.randint(0, SCREEN_HEIGHT),
            )
        )
        self.speed = random.randint(5, 20)
        # moves sprite based on speed, remove when passes left edge
        def update(self):
            self.rect.move_ip(-self.speed, 0)
            if self.rect.right < 0:
                self.kill()
                #How sad for them


pygame.init()
#create screen
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

#custom events for adding a new Enemy
ADDENEMY = pygame.USEREVENT + 1
pygame.time.set_timer(ADDENEMY, 250)
# Instantiate player
player = Player()
enemies = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
#keep the game running!
running = True


#loop time!
while running:
    #look at all the events
    for event in pygame.event.get():
        #did the user hit a key?
        if event.type == KEYDOWN:
            #Was it escape?  uh oh we gotta stop
            if event.key == K_ESCAPE:
                running = False

        elif event.type ==QUIT:
            running = False

        elif event.type == ADDENEMY:
            #Create the new enemy
            new_enemy = Enemy()
            enemies.add(new_enemy)
            all_sprites.add(new_enemy)
    #gets the keys that were just pressed
    pressed_keys = pygame.key.get_pressed()
    #updates location based on keys
    player.update(pressed_keys)
    #updates enemy position
    enemies.update()
    #fill screen with white
    screen.fill((255, 255, 255))
    #Draw the sprites
    for entity in all_sprites:
        screen.blit(entity.surf, entity.rect)
    # Create a surface and pass in a tuple containing legth and width
    surf = pygame.Surface((50, 50))

    
    pygame.display.flip()

As far as I can tell, I have to create an enemy class, then add an event that adds the enemy (ADDENEMY). When that event is called (every 250ms thanks to the timer) it should have an enemy show up that moves to the left until it reaches the end of the display.
I have a group of sprites that are enemies, and a group of all_sprites, and I'm using screen.blit and a for loop to render each entity in all_sprites to the screen. What am I missing? when I run this (along with the bits I've edited out) I see the player sprite fine, and it moves, but I don't see any enemies.

1 Answers

Your sprites are not in the window. All sprites are outside the window because the range was specified incorrectly:

random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100)

random.randint(20, SCREEN_WIDTH + 100),

In addition, there is a problem with Indentation. The method update needs to be is scope of the class Enemy:

class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        # [...]

    # INDENTATION

    #<--|
    def update(self):
        # [...]

Furthermore, see pygame.sprite.Group.draw():

Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]

Rename the attribute surf by image and call all_sprites.draw(screen):

class Player(pygame.sprite.Sprite):
        def __init__(self):
            super(Player, self).__init__()
            self.image = pygame.Surface((75,25))
            self.image.fill((0, 0,0))
            self.rect = self.image.get_rect()
class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super(Enemy, self).__init__()
        self.image = pygame.Surface((20,10))
        self.image.fill((0,0,0))
        self.rect = self.image.get_rect(
            center = (
            random.randint(20, SCREEN_WIDTH + 100),
            random.randint(0, SCREEN_HEIGHT),
            )
        )
        self.speed = random.randint(5, 20) 
while running:
    # [...]

    #for entity in all_sprites:
    #    screen.blit(entity.surf, entity.rect) <---- DELETE


    all_sprites.draw(screen)                   <---- ADD
Related