You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pygame精灵无动画故障排查及代码修正请求

Pygame Sprite动画静态问题修复

问题原因

  1. 动画帧被强制重置:Player类的draw方法中,每次绘制时都会将self.sprite重新赋值为idle动画的第一帧,完全覆盖了update_sprite方法计算出的动画帧,导致动画无法播放。
  2. 逻辑调用顺序错误:主循环中先执行player.loop()再处理按键输入,使得移动速度的更新滞后一帧,移动响应延迟。

修正后的代码

import os
import random
import math
import pygame
from os import listdir
from os.path import isfile, join
pygame.init()

pygame.display.set_caption("Platformer") #set the caption at the top of the window

BG_COLOR = (255,255,255) #White background, dont need it anymore
WIDTH, HEIGHT = 1000, 640 #screen dimensions
FPS = 60
PLAYER_VEL = 5 # the speed of the player

window = pygame.display.set_mode((WIDTH, HEIGHT)) #set the window with sizes

def flip(sprites):
    return [pygame.transform.flip(sprite, True, False) for sprite in sprites]


def load_sprite_sheets(dir1, dir2, width, height, direction=False):
    path = join("assets", dir1, dir2)
    images = [f for f in listdir(path) if isfile(join(path, f))] #if f is a file put in the images list

    all_sprites = {}

    for image in images:
        sprite_sheet = pygame.image.load(join(path, image)).convert_alpha() #loaded transparent bg image

        sprites = []
        for i in range(sprite_sheet.get_width() // width):
            surface = pygame.Surface((width, height), pygame.SRCALPHA, 32)
            rect = pygame.Rect(i * width, 0, width, height)
            surface.blit(sprite_sheet, (0, 0), rect)
            sprites.append(pygame.transform.scale2x(surface))

        if direction:
            all_sprites[image.replace(".png", "") + "_right"] = sprites
            all_sprites[image.replace(".png", "") + "_left"] = flip(sprites)
        else:
            all_sprites[image.replace(".png", "")] = sprites
        
    return all_sprites
            



class Player(pygame.sprite.Sprite): #sprite is useful for perfect pixel collision
    COLOR = (0,0,255)
    GRAVITY = 1
    SPRITES = load_sprite_sheets("MainCharacters" , "MaskDude", 32 , 32 , True)
    ANIMATION_DELAY = 3
    
    def __init__(self, x,y, width , height):
        self.rect = pygame.Rect(x,y,width,height)
        self.x_vel = 0
        self.y_vel = 0
        self.mask = None
        self.direction = "left" # to record which animation to show
        self.animation_count = 0 #   
        self.fall_count = 0
        # 初始化默认 sprite
        self.sprite = self.SPRITES["idle_"+self.direction][0]


    def move(self,dx,dy):
        self.rect.x += dx
        self.rect.y += dy #here we draw only the motion calculated in the next functions
        
    def move_left(self, vel):
        self.x_vel = -vel
        if self.direction != "left":
            self.direction = "left"
            self.animation_count = 0

    def move_right(self, vel):
        self.x_vel = vel
        if self.direction != "right":
            self.direction = "right"
            self.animation_count = 0

    def loop(self , fps):
#        self.y_vel += min(1 , (self.fall_count/fps) * self.GRAVITY)
        self.move(self.x_vel,self.y_vel)

        self.fall_count += 1
        self.update_sprite()

    def update_sprite(self): #is about changing the sprite shape to look walking
        sprite_sheet = "idle"

        if self.x_vel !=0:
            sprite_sheet = "run"

        sprite_sheet_name = sprite_sheet + "_" + self.direction
        sprites = self.SPRITES[sprite_sheet_name]
        sprite_index = (self.animation_count //
                        self.ANIMATION_DELAY) % len(sprites) #set new index every ANIMATION_DELAY = 5
        self.sprite = sprites[sprite_index]          
        self.animation_count += 1

    def draw(self, win):
        # 移除强制重置sprite的代码,直接使用update_sprite设置好的帧
        win.blit(self.sprite , (self.rect.x , self.rect.y))

    
def get_background(name): #name is bg image, this create the bg image position list
    image = pygame.image.load(join("assets", "Background", name))
    _, _, width, height = image.get_rect()
    tiles = [] #list of tles I need to fil my window bg

    for i in range(WIDTH//width + 1):
        for j in range (HEIGHT // height+1):
            pos = tuple([i * width , j*height]) # convert list into tuple
            tiles.append(pos)
        
    return tiles, image # now I now the list of positions to fill the bg and the exact file to use

def draw(window, background, bg_image, player):
    for tile in background:
        window.blit(bg_image, tile) # drawing the image at every position

    player.draw(window)

    pygame.display.update()

def handle_move(player): #check keys and collision
    keys = pygame.key.get_pressed()

    player.x_vel = 0; #as moveleft change the velocity we have to change it to zero so w
    if keys[pygame.K_LEFT]:
        player.move_left(PLAYER_VEL)
    if keys[pygame.K_RIGHT]:
        player.move_right(PLAYER_VEL)

def main(window):
    clock = pygame.time.Clock()
    background, bg_image = get_background("Blue.png")

    player = Player(100,100,50,50)
    run = True
    while(run):
        clock.tick(FPS) #fix the refresh rate to this otherwise it will be dpending on the computer power

        for event in pygame.event.get():
            if event.type == pygame.QUIT: #if teh program detect an event of the user Quiting the game
                run = False
                break
        
        # 先处理按键输入更新速度,再执行loop进行移动和动画更新
        handle_move(player)
        player.loop(FPS)
        draw(window, background, bg_image, player)
    pygame.quit()
    quit() #quiting the  python itself

if __name__ == "__main__":
    main(window) #when we run the file go to the main function with this arg

关键修改点

  • 在Player.__init__中初始化默认的self.sprite,避免绘制时出现未定义的情况。
  • 删除Player.draw中self.sprite = self.SPRITES["idle_"+self.direction][0]这行代码,让update_sprite控制的动画帧正常显示。
  • 调整主循环中handle_move和player.loop的调用顺序,确保移动速度是最新的按键输入值。

内容的提问来源于stack exchange,提问作者aharbiy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:35:22