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

