首页 > 解决方案 > Pygame角色空闲动画

问题描述

我正在使用 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 来减慢它的方法,因为每次我停止移动时它都会冻结游戏。

谢谢

标签: pythonpygame

解决方案


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

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

推荐阅读