'How to draw an image from multiple sprites?

I'm new to programming, trying to make a simple Snake game.

I uploaded three images (16x16px) of a snake (head, body, tail) to a list and wanted to display it with a for loop (each sprite next to each other) but I failed. All I can do is draw the images which are overwriting the last one in my update() method.

I've made some code like adding second [1] (snake_body) to my snake_head image, but I couldn't find a way to display it in a for loop next to each other.

here's some code:

class Snake(pygame.sprite.Sprite):
    def __init__(self, game, apples_eaten):
        # Initialize
        super().__init__()
        self.screen = game.screen
        self.screen_rect = game.screen.get_rect()

        # Movement
        self.direction = 'left'
        self.step = 10

        # Init stats
        self.apples_eaten = 0
        self.current_sprite = 0

        # Create sprites
        self.sprites = []
        self.sprites.append(pygame.image.load(r'C:\Users\Fox\Desktop\Python\Snake\Sprites\Snake\Snake_head.png'))
        self.sprites.append(pygame.image.load(r'C:\Users\Fox\Desktop\Python\Snake\Sprites\Snake\Snake_body.png'))
        for apple in range(apples_eaten):
            self.sprites.append(pygame.image.load(r'C:\Users\Fox\Desktop\Python\Snake\Sprites\Snake\Snake_body.png'))
        self.sprites.append(pygame.image.load(r'C:\Users\Fox\Desktop\Python\Snake\Sprites\Snake\Snake_tail.png'))

        self.image = self.sprites[self.current_sprite]
        self.rect = self.image.get_rect()
        self.rect = self.screen_rect.center

    def update(self):
        self.current_sprite += 1
        if self.current_sprite >= len(self.sprites):
            self.current_sprite = 0
        self.image = self.sprites[self.current_sprite]

How I can draw images from sprite next to each other in a loop? (or any other way?)

I want to make one moving image from 3 sprites linked to each other.



Solution 1:[1]

You have list of images but you need also list of positions.
Every sprite needs own position but you use the same rect for all images.

sprites   = [image1, image2, image3]
positions = [pos1, pos2, pos3]

and later

img = sprites[self.current_sprite]
pos = positions[self.current_sprite]

screen.blit(img, pos)

Or you should keep it as pairs `(image, position)

sprites = [(image1, pos1), (image2, pos2), (image3, pos3)]

and do

img, pos = sprites[self.current_sprite]

screen.blit(img, pos)

PyGame has even real pygame.Sprite which can keep image (pygame.Surface) and positon (pygame.Rect). Function image.load gives you only pygame.Surface.

But for snake which can change its length I would rather keep snake positions as list (without positions of apple and other objects)

snake = [pos1, pos2, pos3, ..., posN]

and I would use first position to draw image with head, last position to draw image with tail, and other positions to draw images with body.

img = head
pos = snake[0]

screen.blit(img, pos)

img = tail
pos = snake[-1]

screen.blit(img, pos)

img = body
for pos in snake[1:-1]
    screen.blit(img, pos)

And when it has to move then I would add new position at the beginning of list and remove last position from list. And when snake eats apple then I would keep last position on list to make snake longer.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1