Aeryes
Aeryes

Reputation: 681

How do I get my images to work as an animation in pygame?

I have read other questions posted here that are related but I can not seem to fit those answers into my state machine which can be found here: https://github.com/Aeryes/Demented

I am trying to create an animation either using a sprite sheet or just an iteration through a list or dict. I have so far managed to get the first image in a list to load as an animation but it will not cycle through the list of 4 images as long as my flag variable which is running = True is true. Instead it will load the first image from the list and hold it on that image until running = False in which case it reverts as intended back to the standstill image.

Here is my current code for my player class without my failed animation attempts:

import pygame as pg
from settings import Music_Mixer, loadCustomFont, States, screen
from time import sleep

"""This section contains entity states which are separate from game and menu states."""
class Player():
    def __init__(self, x, y):
        self.health = 100
        self.speed = 1
        self.screen = screen
        self.imagex = x
        self.imagey = y
        self.running_right = False
        self.running_left = False
        self.rect = pg.draw.rect(self.screen, (255, 0, 0), [self.imagex, self.imagey, 20, 45])
        self.image = pg.image.load('Images/Animations/PlayerRun/Stickman_stand_still.png').convert_alpha()
        self.images = ['Images/Animations/PlayerRun/Stickman_stand_still.png', 'Images/Animations/PlayerRun/Stickman_run_1.png', 'Images/Animations/PlayerRun/Stickman_run_2.png',
        'Images/Animations/PlayerRun/Stickman_run_3.png', 'Images/Animations/PlayerRun/Stickman_run_4.png']

    #Moves the player and begins the animation phase.
    def move_player(self, speed):
        self.pressed = pg.key.get_pressed()

        #Move left and start left run animation.
        if self.pressed[pg.K_a]:
            self.imagex -= 5

        #Move right and start right run animation
        if self.pressed[pg.K_d]:
            self.running_right = True
            self.imagex += 5
        elif not self.pressed[pg.K_d]:
            self.running_right = False

        #Move up and start jump animation.
        if self.pressed[pg.K_w]:
           self.imagey -= 5

        #Move down and start either crouch.
        if self.pressed[pg.K_s]:
            self.imagey += 5

    #Animates the running movement of the player.
    def runAnim(self):

        if self.running_right:
            pass

        elif self.running_right == False:
            self.image = pg.image.load('Images/Animations/PlayerRun/Stickman_stand_still.png').convert_alpha()

    #draws the player to the screen.
    def draw_entity(self):
        screen.blit(self.image, (self.imagex, self.imagey))

I have looked here: Animation in with a list of images in Pygame

And here: Animated sprite from few images

Upvotes: 1

Views: 781

Answers (1)

skrx
skrx

Reputation: 20488

  • Load the images and put them into lists.
  • Add an index, a timer and an images (the current image list/animation) attribute to the class.
  • When the user presses one of the movement keys, swap the image list.
  • To animate the images, first pass the dt (delta time) to the player's update method and subsequently to the other methods that need it. Increment the timer attribute and, after the desired time interval, increment the index and use it to swap the image.

That's basically all you need to do, but maybe you have to adjust a few things.


import pygame as pg


pg.init()
screen = pg.display.set_mode((640, 480))

# Load images once when the program starts. Put them into lists, so that
# you can easily swap them out when the player changes the direction.
STICKMAN_IDLE = [pg.image.load(
    'Images/Animations/PlayerRun/Stickman_stand_still.png').convert_alpha()]
# You could use a list comprehension here (look it up).
STICKMAN_RUN = [
    pg.image.load('Images/Animations/PlayerRun/Stickman_run_1.png').convert_alpha(),
    pg.image.load('Images/Animations/PlayerRun/Stickman_run_2.png').convert_alpha(),
    pg.image.load('Images/Animations/PlayerRun/Stickman_run_3.png').convert_alpha(),
    pg.image.load('Images/Animations/PlayerRun/Stickman_run_4.png').convert_alpha(),
    ]


class Player:

    def __init__(self, x, y):
        self.pos_x = x
        self.pos_y = y

        self.images = STICKMAN_IDLE
        self.image = self.images[0]
        self.rect = self.image.get_rect(center=(x, y))

        self.anim_index = 0
        self.anim_timer = 0

    def move_player(self, dt):
        """Move the player."""
        self.pressed = pg.key.get_pressed()

        if self.pressed[pg.K_a]:
            self.pos_x -= 5  # Move left.
            self.images = STICKMAN_RUN_RIGHT  # Change the animation.
        if self.pressed[pg.K_d]:
            self.pos_x += 5  # Move right.
            self.images = STICKMAN_RUN_RIGHT  # Change the animation.
        if not self.pressed[pg.K_d] and not self.pressed[pg.K_a]:
            self.images = STICKMAN_IDLE  # Change the animation.

        # Update the rect because it's used to blit the image.
        self.rect.center = self.pos_x, self.pos_y

    def animate(self, dt):
        # Add the delta time to the anim_timer and increment the
        # index after 70 ms.
        self.anim_timer += dt
        if self.anim_timer > .07:  # After 70 ms.
            self.anim_timer = 0  # Reset the timer.
            self.anim_index += 1  # Increment the index.
            self.anim_index %= len(self.images)  # Modulo to cycle the index.
            self.image = self.images[self.anim_index]  # And switch the image.

    def update(self, dt):
        self.move_player(dt)
        self.animate(dt)

    def draw(self, screen):
        screen.blit(self.image, self.rect)


def main():
    clock = pg.time.Clock()
    player = Player(100, 300)
    done = False

    while not done:
        # dt (delta time) = time in ms since previous tick.
        dt = clock.tick(30) / 1000

        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True

        player.update(dt)  # Pass the delta time to the player.

        screen.fill((30, 30, 30))
        player.draw(screen)
        pg.display.flip()


if __name__ == '__main__':
    main()
    pg.quit()

Upvotes: 2

Related Questions