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

Pygame按空格触发攻击动画报IndexError列表索引越界问题

错误原因分析
  • 索引越界的核心原因:你全局定义的walkLeft、walkRight列表只有3个元素(有效索引为0、1、2),但你在循环的绘制逻辑中设置了walkCount + 1 >= 12才重置walkCount,当walkCount增长到9及以上时,walkCount//3的结果会是3、4,超出了列表的有效索引范围,直接触发IndexError。
  • 第二套重绘逻辑完全不生效的原因:
    1. redrawGameWindow2内部定义的walkLeft、walkRight是局部变量,不会修改全局的动画列表,全局列表始终只有3个元素
    2. 你把redrawGameWindow2的定义写在了主循环内部,每次循环都会重复定义函数,且你是在执行完绘制逻辑之后才调用redrawGameWindow2,哪怕修改了列表也不会对本次的绘制生效
    3. 代码语法存在错误,walkRight赋值语句中间错误换行,会直接触发语法报错
修复方案

你不需要定义两套重绘函数,只需要新增攻击状态标记,统一在一个重绘逻辑里处理不同状态的动画即可,修复后的可运行代码如下:

import pygame
pygame.init()

win = pygame.display.set_mode((1280,800))
pygame.display.set_caption("First Game")

# 提前加载所有动画资源,不要在循环里重复加载
walkLeft = [pygame.image.load('/Users/arnav/Downloads/Jokerattack1.png'), 
            pygame.image.load('/Users/arnav/Downloads/Jokerattack2.png'), 
            pygame.image.load('/Users/arnav/Downloads/Jokerattack3.png')]
walkRight = [pygame.image.load('/Users/arnav/Downloads/Jokerattack1Right.png'), 
             pygame.image.load('/Users/arnav/Downloads/Jokerattack2Right.png'), 
             pygame.image.load('/Users/arnav/Downloads/Jokerattack3Right.png')]
# 提前加载攻击动画
attackLeft = [pygame.image.load('/Users/arnav/Downloads/Jokerattack1.png'), 
              pygame.image.load('/Users/arnav/Downloads/Jokerattack2.png'), 
              pygame.image.load('/Users/arnav/Downloads/Jokerattack3.png'), 
              pygame.image.load('/Users/arnav/Downloads/Jokerattack4.png')]
attackRight = [pygame.image.load('/Users/arnav/Downloads/Jokerattack1Right.png'), 
               pygame.image.load('/Users/arnav/Downloads/Jokerattack2Right.png'), 
               pygame.image.load('/Users/arnav/Downloads/Jokerattack3Right.png'), 
               pygame.image.load('/Users/arnav/Downloads/Jokerattack3Right.png')]

Joker1 = pygame.image.load('/Users/arnav/Downloads/Joker.png')
char = pygame.transform.scale(Joker1, (80, 132)) 
bg1 = pygame.image.load('/Users/arnav/Downloads/GothamCity.jpg')
bg = pygame.transform.scale(bg1, (1280, 800))
x = 0
y = 400
width = 40
height = 60
vel = 5

clock = pygame.time.Clock()

isJump = False
jumpCount = 10
isAttack = False # 新增攻击状态标记
attackCount = 0 # 攻击动画计数器

left = False
right = False
walkCount = 0

def redrawGameWindow():
    global walkCount, attackCount, isAttack
    win.blit(bg, (0,0))
    
    if isAttack:
        # 处理攻击动画
        if attackCount +1 >= 12: # 4帧动画,每帧显示3个tick,总共12个tick完成一轮
            attackCount = 0
            isAttack = False # 攻击动画播放完结束攻击状态
        if left:
            win.blit(attackLeft[attackCount//3], (x,y))
        else:
            win.blit(attackRight[attackCount//3], (x,y))
        attackCount +=1
    else:
        # 处理普通行走/站立动画
        if walkCount + 1 >= 9: # 3帧动画,每帧3tick,总共9tick一轮
            walkCount = 0
        if left:  
            win.blit(walkLeft[walkCount//3], (x,y))
            walkCount += 1                          
        elif right:
            win.blit(walkRight[walkCount//3], (x,y))
            walkCount += 1
        else:
            win.blit(char, (x, y))
            walkCount = 0
    pygame.display.update() 

run = True
while run:
    clock.tick(12)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()
    # 攻击状态下不响应移动和跳跃
    if not isAttack:
        if keys[pygame.K_SPACE]:
            isAttack = True
            attackCount = 0
        else:
            if (keys[pygame.K_LEFT] or keys[ord('a')]) and x > vel: 
                x -= vel
                left = True
                right = False
            elif (keys[pygame.K_RIGHT] or keys[ord('d')]) and x < 1280 - vel - width:  
                x += vel
                left = False
                right = True
            else: 
                left = False
                right = False
                walkCount = 0

            if not(isJump):
                if keys[pygame.K_UP] or keys[ord('w')]:
                    isJump = True
                    left = False
                    right = False
                    walkCount = 0
            else:
                if jumpCount >= -10:
                    y -= (jumpCount * abs(jumpCount)) * 0.5
                    jumpCount -= 1
                else: 
                    jumpCount = 10
                    isJump = False
    # 统一调用重绘函数
    redrawGameWindow()

pygame.quit()
修复点说明
  • 提前加载所有动画资源,避免在循环中重复加载拖慢性能
  • 新增isAttack状态标记和attackCount计数器,区分普通行走和攻击状态,避免动画逻辑冲突
  • 不同状态的动画分别设置对应的walkCount重置阈值,保证索引不会超出列表范围
  • 修复了按键判断的优先级,攻击时不响应移动操作,避免动画混乱
  • 移除了冗余的重绘函数和循环内的绘制逻辑,代码结构更清晰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 08:06:03