【问题标题】:How do I get my images to work as an animation in pygame?如何让我的图像在 pygame 中作为动画工作?
【发布时间】:2018-08-27 10:10:57
【问题描述】:

我已阅读此处发布的其他相关问题,但我似乎无法将这些答案放入我的状态机中,可以在此处找到:https://github.com/Aeryes/Demented

我正在尝试使用精灵表或仅通过列表或字典进行迭代来创建动画。到目前为止,我已经设法让列表中的第一个图像作为动画加载,但只要我正在运行的标志变量 = True 为真,它就不会循环遍历 4 个图像的列表。相反,它会从列表中加载第一个图像并将其保留在该图像上,直到 running = False 在这种情况下,它会按预期恢复到静止图像。

这是我当前的播放器类代码,没有失败的动画尝试:

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

我看过这里:Animation in with a list of images in Pygame

在这里:Animated sprite from few images

【问题讨论】:

    标签: python-3.x animation pygame


    【解决方案1】:
    • 加载图像并将它们放入列表中。
    • 为类添加一个索引、一个计时器和一个images(当前图像列表/动画)属性。
    • 当用户按下其中一个移动键时,交换图像列表。
    • 要为images 设置动画,首先将dt (delta time) 传递给玩家的update 方法,然后传递给其他需要它的方法。增加 timer 属性,并在所需的时间间隔后增加索引并使用它来交换图像。

    这就是你需要做的所有事情,但也许你需要调整一些东西。


    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()
    

    【讨论】:

    • 我已经尝试添加索引无济于事。我的更新类由 Controller 类控制,该类指示运行的状态。 Player 没有更新方法,因为它没有继承它继承 Sprite 的 States 类。它确实有一个在 LevelOne 更新方法中更新的 draw 方法。
    • 我不确定我是否理解您的问题。 “更新课程”是什么意思?玩家对象的update方法应该在当前游戏场景/状态每一帧的update方法中调用,而不是在Control类中。
    • 我使用状态机来控制整个游戏。查看我的 github 链接以了解我在说什么。编辑:我试过你说的,但现在我得到这个错误 TypeError: argument 1 must be pygame.Surface, not builtin_function_or_method
    • 我让它工作了。谢谢您的帮助 !!!只是对我的代码进行了一些修改。
    猜你喜欢
    • 2017-07-14
    • 2019-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 2019-06-07
    • 1970-01-01
    • 2015-10-03
    相关资源
    最近更新 更多