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

Pygame实现角色冲刺动画加速时出现列表索引越界问题

问题描述

已实现角色行走移动与对应行走动画效果,需要在提升角色移动速度的同时加快动画帧循环切换速度,实现奔跑视觉效果。
以下为保留向上移动逻辑的Player类核心代码:

# Variables

walk_up = ["up1.png", "up2.png" .. etc up to "up7.png"]

image_count = len(walk_up)
frame_count = 8
walk_count = 0

class Player(pygame.sprite.Sprite):
    def __init__(self, position, image):
        super().__init__()
        self.animg = image
        self.image = load(path("Images", "Player", "Movement", self.animg)).convert_alpha()
        self.rect = self.image.get_rect(topleft=position)
        self.last = ""
  
    def move(self, keypress):
        global walk_count
        global frame_count

        x = 4
        y = 4

        # Reset walk_count when it gets to the max number
        if walk_count >= image_count * frame_count:
            walk_count = 0

        if keypress[K_UP]:
            self.rect.move_ip(0, -y)
            self.image = walk_up[walk_count // frame_count]
            display.blit(self.image, self.rect)
            walk_count += 1
            self.last = "up"
        if keypress[K_DOWN]:
            etc.

        # When you stop moving the image shown is the first in the list
        elif self.last != "":
            if self.last == "up":
                self.image = walk_up[0]

        else:
            walk_count = 0

现有动画逻辑:self.image = walk_up[walk_count // frame_count] 代表frame_count为8时,单张动画图持续显示8个游戏帧后切换到下一张。修改x、y值可直接提升移动速度,但在move方法中添加Shift按键检测、通过修改frame_count实现冲刺动画加速时,会触发list index out of range列表索引越界报错。

报错原因

索引越界的核心是walk_count的重置阈值完全依赖初始固定值frame_count=8计算。当按住Shift把frame_count改小(动画速度变快)时,walk_count // frame_count的计算结果会超出walk_up列表的索引范围(列表共7个元素,合法索引为0-6)。
举个实际场景:初始frame_count=8时重置阈值为7*8=56,walk_count最大到55时55//8=6,刚好对应最后一张动画图;如果冲刺时frame_count改为4,walk_count增长到28时还没触发重置,28//4=7,列表不存在索引为7的元素,直接触发报错。

修复方案

不要用全局变量存储动画计数和帧间隔,把动画状态绑定到Player实例属性上,同时把重置判断逻辑改为动态计算,不依赖固定全局值。修改后的核心代码如下:

from pygame.locals import K_UP, K_DOWN, K_LSHIFT, K_RSHIFT

# 动画资源列表
walk_up = ["up1.png", "up2.png", "up3.png", "up4.png", "up5.png", "up6.png", "up7.png"]
image_count = len(walk_up)
# 配置项:行走/冲刺状态下的单帧持续游戏帧数(值越小动画播放越快)
WALK_FRAME_STEP = 8
RUN_FRAME_STEP = 4
# 配置项:行走/冲刺状态下的单帧移动像素距离
WALK_SPEED = 4
RUN_SPEED = 8

class Player(pygame.sprite.Sprite):
    def __init__(self, position, image):
        super().__init__()
        self.animg = image
        self.image = load(path("Images", "Player", "Movement", self.animg)).convert_alpha()
        self.rect = self.image.get_rect(topleft=position)
        self.last_dir = ""
        # 动画计数器改为实例属性,多角色场景下不会计数混乱
        self.anim_tick = 0

    def move(self, keypress):
        # 判断当前是否触发冲刺
        is_running = keypress[K_LSHIFT] or keypress[K_RSHIFT]
        # 动态取当前状态对应的动画步长、移动速度
        current_frame_step = RUN_FRAME_STEP if is_running else WALK_FRAME_STEP
        current_speed = RUN_SPEED if is_running else WALK_SPEED

        # 动态计算动画计数重置阈值,帧步长变化时也不会越界
        if self.anim_tick >= image_count * current_frame_step:
            self.anim_tick = 0

        is_moving = False
        if keypress[K_UP]:
            self.rect.move_ip(0, -current_speed)
            self.image = walk_up[self.anim_tick // current_frame_step]
            display.blit(self.image, self.rect)
            self.anim_tick += 1
            self.last_dir = "up"
            is_moving = True
        # 其余方向移动逻辑和向上逻辑完全一致,替换对应动画列表、移动方向即可
        if keypress[K_DOWN]:
            pass

        # 停止移动时回到待机动画
        if not is_moving:
            if self.last_dir == "up":
                self.image = walk_up[0]
            # 停止时重置动画计数,下次移动从第一帧开始
            self.anim_tick = 0

关键改动说明

  • 移除全局的walk_count、frame_count变量,动画计数绑定到Player实例,避免全局状态混乱
  • 帧间隔、移动速度根据当前按键状态动态取值,冲刺状态判断独立
  • 动画计数重置阈值随当前帧间隔动态计算,从根本上避免索引越界问题
  • 可直接通过修改RUN_FRAME_STEP、RUN_SPEED的数值自由调整奔跑时的动画速度和移动速度的匹配度,数值越小动画播放越快。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 05:15:31