【问题标题】:Pygame character idle animationPygame角色空闲动画
【发布时间】:2020-04-13 12:32:50
【问题描述】:

我正在使用 Python 模块 Pygame 制作 2D 平台游戏。我已经为所述玩家制作了背景、角色和动作。您可以使用键盘上的 a & d 移动并使用 SPACE 跳跃。但是我不知道如何为玩家制作空闲动画。我有跑步动画,但是我还没有制作精灵,所以我只是使用了空闲的图片集。

这是我的代码:

import pygame, time, itertools

pygame.init()

# background image
walkRight = pygame.image.load('idle1.png')
walkLeft = pygame.image.load('idle1.png')
bg = pygame.image.load("background.png")
idle = [pygame.image.load('idle1.png'), pygame.image.load('idle2.png'), pygame.image.load('idle3.png')]
standcount = True

clock = pygame.time.Clock()

# jump
isJump = False
jumpcount = 10

# window
display_width = 1000
display_height = 600
win = pygame.display.set_mode((display_width, display_height))

# title & icon
pygame.display.set_caption("Grand Theft Ewok")
icon = pygame.image.load('bear.png')
pygame.display.set_icon(icon)

# player creds
x = 50
y = 430
vel = 10

# playerIMG
playerIMG = pygame.image.load('player.png')


def player(x, y):
    global standcount
    global walkcount
    win.blit(bg, (0, 0))
    # win.blit(playerIMG, (x,y))

    if walkcount + 1 >= 9:
        walkcount = 0

    if standcount + 1 >= 9:
        standcount = 0

    if left:
        win.blit(idle[walkcount // 3], (x, y))
        walkcount += 1
    elif right:
        win.blit(idle[walkcount // 3], (x, y))
        walkcount += 1
    elif standcount:
        p = 0
        for frame in idle:
            win.blit(idle[p], (x, y))
            p += 1
            if p >= 2:
                p = 0
                continue

    pygame.display.update()


# game loop
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # movement
    keys = pygame.key.get_pressed()

    if keys[pygame.K_a] and x > (vel - 25):
        x -= vel
        left = True
        right = False
    elif keys[pygame.K_d] and x < 835:
        x += vel
        right = True
        left = False
    else:
        right = False
        left = False
        walkcount = 0
        standcount = True

    if not (isJump):
        if keys[pygame.K_SPACE]:
            isJump = True
            left = False
            right = False

    else:
        if jumpcount >= -10:
            neg = 1
            if jumpcount < 0:
                neg = -1
            y -= (jumpcount ** 2) * 0.5 * neg
            jumpcount -= 1
        else:
            isJump = False
            jumpcount = 10

    player(x, y)
    pygame.display.update()

pygame.quit()

在播放器功能下,您可以看到我尝试使用 for 循环的位置,但它不起作用。

我正在使用 Python 3.8。

祝大家好运。

待在室内,谢谢。

编辑 我已经找到了如何使用这个来制作空闲动画:

    elif standcount:
        p = 0
        for frame in idle:
            win.blit(idle[standcount], (x, y))

            standcount += 1

            #pygame.display.update()

            if standcount >= 2:
                standcount = 0
                continue
            pygame.display.update()

但是,它迭代列表的速度非常快。我想不出一种不使用 time.sleep 来减慢它的方法,因为这样每次我停止移动时它都会冻结游戏。

谢谢

【问题讨论】:

    标签: python pygame


    【解决方案1】:

    您不需要循环,只需执行与步行相同的操作即可:

    if left:
        win.blit(idle[walkcount // 3], (x, y))
        walkcount += 1
    elif right:
        win.blit(idle[walkcount // 3], (x, y))
        walkcount += 1
    else:
        win.blit(idle[standcount // 3], (x, y))
        standcount += 1
    

    使用循环意味着它将在同一帧中将所有图像相互叠加,这意味着您只会看到顶部/最后一个。您为步行动画所做的工作完美无缺。


    另外,您应该只有一个pygame.display.update()。您应该只在每帧结束时更新屏幕,而不是在一帧中更新多次。由于您在更新屏幕之前调用player(),因此您可以摆脱其中一个,因为一个不会做任何事情


    所以我发现了问题,你有一个 standcount = True 会将其重置为 1,摆脱它解决了问题

    以下是编辑后的完整代码:

    import pygame, time, itertools
    
    pygame.init()
    
    # background image
    walkRight = pygame.image.load('idle1.png')
    walkLeft = pygame.image.load('idle1.png')
    bg = pygame.image.load("background.png")
    idle = [pygame.image.load('idle1.png'), pygame.image.load('idle2.png'), pygame.image.load('idle3.png')]
    standcount = 0 # change it to an int, not a bool
    
    clock = pygame.time.Clock()
    
    # jump
    isJump = False
    jumpcount = 10
    
    # window
    display_width = 1000
    display_height = 600
    win = pygame.display.set_mode((display_width, display_height))
    
    # title & icon
    pygame.display.set_caption("Grand Theft Ewok")
    icon = pygame.image.load('bear.png')
    pygame.display.set_icon(icon)
    
    # player creds
    x = 50
    y = 430
    vel = 10
    
    # playerIMG
    playerIMG = pygame.image.load('player.png')
    
    
    def player(x, y):
        global standcount
        global walkcount
        win.blit(bg, (0, 0))
        # win.blit(playerIMG, (x,y))
    
        if walkcount + 1 >= 9:
            walkcount = 0
    
        if standcount + 1 >= 9:
            standcount = 0
    
        if left:
            win.blit(idle[walkcount // 3], (x, y))
            walkcount += 1
        elif right:
            win.blit(idle[walkcount // 3], (x, y))
            walkcount += 1
        else:
            win.blit(idle[standcount // 3], (x, y))
            standcount += 1        
    
        pygame.display.update()
    
    
    # game loop
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
    
        # movement
        keys = pygame.key.get_pressed()
    
        if keys[pygame.K_a] and x > (vel - 25):
            x -= vel
            left = True
            right = False
        elif keys[pygame.K_d] and x < 835:
            x += vel
            right = True
            left = False
            #you could put standcount = 0 here to reset animation after walking
        else:
            right = False
            left = False
            walkcount = 0
            #got rid of standcount = True
        if not (isJump):
            if keys[pygame.K_SPACE]:
                isJump = True
                left = False
                right = False
    
        else:
            if jumpcount >= -10:
                neg = 1
                if jumpcount < 0:
                    neg = -1
                y -= (jumpcount ** 2) * 0.5 * neg
                jumpcount -= 1
            else:
                isJump = False
                jumpcount = 10
    
        player(x, y)
        pygame.display.update()
    
    pygame.quit()
    

    至于速度:

    有2个选项,

    A) 等待一段时间(我推荐)

    B) 等待一定数量的帧(不推荐)

    最好做时间,因为这样性能不会影响速度

    所以你已经有时间导入你可以这样做:

    idle_frame_start = time.time() # get the current time - very accurate
    walk_frame_start = time.time()
    
    def player(x, y):
        global standcount, idle_frame_start
        global walkcount, walk_frame_start
        # win.blit(playerIMG, (x,y))
    
        if walkcount + 1 >= 4: #if the count is more than amount of images
            walkcount = 0
    
        if standcount + 1 >= 4:
            standcount = 0
    
        if left:
            win.blit(idle[walkcount], (x, y))
            if time.time() - walk_frame_start > 0.8:
                walkcount += 1
                walk_frame_start = time.time()
        elif right:
            win.blit(idle[walkcount], (x, y))
            if time.time() - walk_frame_start > 0.8:
                walkcount += 1
                walk_frame_start = time.time()
        else:
            win.blit(idle[standcount], (x, y))
            if time.time() - idle_frame_start > 0.8: # if the time difference is bigger than 0.8s
                standcount += 1        
                idle_frame_start = time.time() # reset the start time
    
        pygame.display.update()
    

    【讨论】:

    • 谢谢,我试过了,但它仍然没有为我播放动画。
    • @HomeMadeMusic 尝试将脚本顶部的 standcount = True 更改为 standcount = 0
    • 再次感谢,但它仍然没有像以往那样做动画。
    • 是的,谢谢。您是否认为他们的方法可以减慢速度,但它的移动速度适中。这意味着看起来角色正在呼吸,所以每张图片应该有大约 0.8 秒的延迟。谢谢
    • 谢谢您,先生,完美解决了问题,祝您玩得愉快,注意安全!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    相关资源
    最近更新 更多