0

Here is my code.

jack_right_1 = pg.image.load(os.path.join(img_folder, "jack_right_1.png")).convert()
jack_right_2 = pg.image.load(os.path.join(img_folder, "jack_right_2.png")).convert()
jack_right_3 = pg.image.load(os.path.join(img_folder, "jack_right_3.png")).convert()

player_images = [jack_right_1, jack_right_2, jack_right_3]

class Player(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = player_images
        self.rect = self.image.get_rect()
        self.pos = vec(WIDTH - 650, HEIGHT - 700)
        self.standing = False
        self.vel = vec(0, 0)
        self.acc = vec(0, 0)

    def update(self):
        self.acc = vec(0, PLAYER_GRAVITY)
        keystate = pg.key.get_pressed()
        if keystate[pg.K_LEFT]:
            player.image = pg.image.load(player_images[counter])
            counter = (counter + 1) % len(player_images)

For some reason, whenever I try to run it, it says that 'list' object has no attribute 'get_rect'. I know you cannot get a rect from a list, but then how do you make an image list and get the rect for each image?

Evan Yang
  • 125
  • 1
  • 8

2 Answers2

1

The image attribute of a pygame.sprite.Sprite has to be a single surface. Assign only the first image of the player_images to self.image. The error is raised because you call self.rect = self.image.get_rect() but your self.image is a list which doesn't have a get_rect method.

You also need an attribute to keep track of the index of the current image (I call it self.counter in the following example).

Now to update the image, you increment the self.counter and use modulo len(player_images) to avoid IndexErrors. Then you use the self.counter index to update the self.image self.image = player_images[self.counter].

class Player(pg.sprite.Sprite):

    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.counter = 0  # Index of the current image.
        # Assign the first player image.
        self.image = player_images[self.counter]
        self.pos = vec(WIDTH - 650, HEIGHT - 700)
        # Now get_rect works. Set the center or topleft to self.pos.
        self.rect = self.image.get_rect(center=self.pos)
        self.standing = False
        self.vel = vec(0, 0)
        self.acc = vec(0, 0)

    def update(self):
        self.acc = vec(0, PLAYER_GRAVITY)
        keystate = pg.key.get_pressed()
        if keystate[pg.K_LEFT]:
            # Increment the counter.
            self.counter = (self.counter + 1) % len(player_images)
            # And finally change the image.
            self.image = player_images[self.counter]
skrx
  • 19,980
  • 5
  • 34
  • 48
  • Also, don't load images in methods that get called all the time. Load them globally like `jack_right1` and then reuse them in your program. --- `pg.key.get_pressed()` should probably be called in your main loop. Then you can pass the `keystate` list to all sprites that need it. – skrx Jul 18 '17 at 08:19
  • Thank you for your help. I have it working now. But, how do I control the speed at which the image switches? – Evan Yang Jul 18 '17 at 19:25
  • To control the animation speed, you can use a timer similar to [this one](https://stackoverflow.com/a/44035094/6220679) and increment the image index when the time is up. – skrx Aug 02 '18 at 14:46
0

It looks like you are pretty close! The problem is that player_images (and therefore self.image) actually stores a list of Surface objects rather an individual Surface. If you want to store a list of Rect objects, you could loop through them like so:

class Player(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.images = player_images
        self.rects = []
        for image in self.images:
            self.rects.append(image.get_rect())

Alternatively, if you need a one-liner which does the same thing, consider a list comprehension instead:

class Player(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.images = player_images
        self.rects = [image.get_rect() for image in self.images]
CodeSurgeon
  • 2,435
  • 2
  • 15
  • 36