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

Pygame实现单击右键后角色冲刺攻击动画完整播放

Pygame 冲刺攻击功能修复方案

核心问题定位

  • 动画松手即断:主循环中强制将攻击状态与鼠标右键按下状态绑定,只要检测到右键抬起就直接关闭攻击状态,导致必须全程按住右键才能播动画
  • 动画循环不退出:攻击动画帧计数到达阈值后直接重置循环,没有设置“播完即退出攻击状态”的判断,只要攻击状态开启就会无限重复播放
  • 触发逻辑不严谨:没有做攻击状态的互斥判断,长按右键会重复触发攻击流程,且动画播放过程中会被移动、跳跃输入随意打断

具体修复步骤

  1. 解绑攻击状态与鼠标按键状态
    直接删除主循环中以下错误逻辑,攻击状态的关闭不再由鼠标是否按住决定:
# 完全删除这段代码
elif pygame.mouse.get_pressed()[2] is False:
    man1.right = False
    man1.left = False
    man1.isAtk_with_mvmt = False
    man1.walkCount = 0
  1. 修正攻击动画播放逻辑,实现播完自动退出
    修改player类的draw方法中攻击动画的计数与渲染逻辑,不再无脑重置计数循环,而是在播放完所有动画帧后自动关闭攻击状态、重置计数:
def draw(self, win):
    # 保留走路、待机动画的原有计数重置逻辑
    if self.walkCount + 1 >= 30:
        self.walkCount = 0
    if self.idleCount + 1 >= 30:
        self.idleCount = 0

    # 攻击状态优先级最高,先判断
    if self.isAtk_with_mvmt:
        # 计算当前要渲染的帧序号
        frame_idx = self.atk_with_mvmtCount // 6
        # 判断是否已经播完所有攻击帧
        if frame_idx >= len(atk_with_mvmt):
            self.isAtk_with_mvmt = False
            self.atk_with_mvmtCount = 0
            # 重置其他动画计数,切回待机/走路时不跳帧
            self.walkCount = 0
            self.idleCount = 0
        else:
            win.blit(atk_with_mvmt[frame_idx], (self.x, self.y))
            self.atk_with_mvmtCount += 1
    elif self.left:
        win.blit(walkLeft[self.walkCount // 3], (self.x, self.y))
        self.walkCount += 1
    elif self.right:
        win.blit(walkRight[self.walkCount // 3], (self.x, self.y))
        self.walkCount += 1
    else:
        win.blit(idleForm[self.idleCount // 3], (self.x, self.y))
        self.idleCount += 1
  1. 优化攻击触发逻辑,避免重复触发
    修改鼠标右键事件的监听逻辑,增加状态互斥判断,只有当前不在攻击、跳跃状态时才能触发新的攻击,触发时重置攻击帧计数,保证每次都从第一帧开始播放:
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        run = False
    # 用event.button判断右键更准确,值为3对应鼠标右键
    if event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
        # 非攻击状态下才能触发,防止长按重复触发
        if not man1.isAtk_with_mvmt:
            man1.isAtk_with_mvmt = True
            man1.atk_with_mvmtCount = 0
            # 原有冲刺位移,想要平滑冲刺可以把位移拆分到攻击帧更新时逐帧加
            man1.x += man1.vel * 25
            man1.right = False
            man1.left = False
  1. 增加攻击状态输入锁(按需调整)
    如果要求攻击动画完整播放、不被移动/跳跃打断,就把左右移动、跳跃的输入处理逻辑放到非攻击状态的判断分支里;如果需要允许玩家主动打断攻击,跳过这步即可:
keys = pygame.key.get_pressed()
# 仅非攻击状态下响应移动、跳跃输入
if not man1.isAtk_with_mvmt:
    if keys[pygame.K_LEFT]:
        man1.x -= man1.vel
        man1.left = True
        man1.right = False
    elif keys[pygame.K_RIGHT]:
        man1.x += man1.vel
        man1.left = False
        man1.right = True
    else:
        man1.left = False
        man1.right = False
        man1.walkCount = 0

    # 跳跃逻辑
    if not man1.isJump:
        if keys[pygame.K_UP]:
            man1.isJump = True
            man1.right = False
            man1.left = False
            man1.walkCount = 0
# 原有跳跃的位移逻辑不受影响,正常保留
if man1.isJump:
    if man1.jumpCount >= -10:
        man1.y -= (man1.jumpCount * abs(man1.jumpCount * 0.7)) * 0.35
        man1.jumpCount -= 1
    else:
        man1.jumpCount = 10
        man1.isJump = False
  1. 清理冗余代码
    redrawGameWindow函数里的三个全局变量声明完全多余,相关属性都是player类的实例属性,直接删掉这几行即可,避免变量冲突:
def redrawGameWindow():
    # 删掉下面三行冗余的global声明
    # global walkCount
    # global idleCount
    # global atk_with_mvmtCount
    win.blit(background, (0, 0))
    man1.draw(win)
    pygame.display.update()

最终效果

修改完成后,单击一次鼠标右键即可触发完整冲刺攻击流程:

  • 不需要持续按住右键,松开按键动画也不会中途终止
  • 攻击动画播放一轮后自动退出,不会循环重复播放
  • 动画结束后自动回到常规待机/移动逻辑,状态切换无跳帧

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 09:45:38