Pygame敌人手臂攻击时Y坐标异常跳动问题修复
Pygame Boss手臂碰撞时Y坐标glitch问题根因与修复
核心问题根因
- 多分支无互斥同帧覆盖坐标:现有代码为平铺式顺序判断,无状态优先级隔离,一帧内多个会修改
arms1.y的分支可同时触发,先后给Y坐标赋值完全不同的计算结果,直接造成画面跳变。典型触发场景为:玩家与launch1.rect碰撞时,既会进入hitting分支计算浮动Y值,又可能因为前置状态未完全清除,触发待机浮动、攻击抬升、下落等分支的Y赋值逻辑,单帧内Y坐标被反复改写。 - 时间计数器无隔离:不同动画阶段共用同一个
arms1.time变量作为余弦计算的角度参数,状态切换时若没有正确重置计数器,会导致余弦值相位乱跳,计算出的Y偏移突然出现大幅正负跳变。 - 状态标记未做进入即清零校验:进入某一状态分支时没有同步关闭其他可能修改坐标的状态标记,残留的状态位会持续触发其他分支的坐标更新。
可落地修复方案
- 建立带优先级的状态机逻辑:所有修改手臂坐标的分支按状态优先级从高到低排列,用
if/elif做互斥绑定,确保一帧内只有一个逻辑有权修改arms1.y,高优先级状态触发时直接跳过低优先级的坐标更新逻辑。 - 拆分独立的时间计数器:为待机浮动、攻击抬升、下落攻击三个动画阶段分别绑定独立的时间变量,状态切换时仅重置对应动画的计数器,彻底避免余弦计算的相位混乱。
- 状态进入时的标记清洗:当触发Boss跟随玩家的瞄准状态时,立刻将攻击、暂停等其他状态标记强制设为False,从根源上杜绝其他分支越权修改坐标。
修正后核心逻辑参考
# 攻击判定检测(不涉及坐标修改,可独立放置) if hittings2: if playerman.rect.colliderect(arms1.sing1): attack1 = True # 最高优先级:手臂碰地面触发停留抬升 if arms1.rect.colliderect(collidtest3.rect): pausemove = True attacks2 = False attack1 = False # 最高优先级:停留抬升阶段逻辑 if pausemove: if attack1timer < 270: attack1timer += 1 arms1.y -= 1 hittings2 = False else: hitting = True hittings2 = True pausemove = False attack1timer = 0 arms1.float_time = 0 # 重置浮动时间,避免相位跳变 # 第二优先级:攻击前置抬升动画 if attack1: hittings2 = False arms1.y = math.cos(math.radians(arms1.lift_time)) * 95 arms1.lift_time += 1 if arms1.lift_time >= 190: attack1 = False arms1.lift_time = 0 attacks2 = True hittings2 = False hitting = False # 第三优先级:手臂下落攻击动画 if attacks2: if not arms1.rect.bottom > collidtest3.rect.bottom: arms1.y += math.cos(math.radians(arms1.fall_time)) * 15 arms1.fall_time += 1 if arms1.fall_time >= 190: arms1.fall_time = 0 # 第四优先级:瞄准玩家的跟随浮动状态(仅上层状态全不触发时执行) elif hitting: if playerman.rect.colliderect(launch1.rect): # 进入状态时清洗其他标记,避免交叉更新 attacks2 = False attack1 = False pausemove = False if arms1.x < playerman.x - 170: arms1.x += playerman.speed if arms1.x > playerman.x - 190: arms1.x -= playerman.speed arms1.y = math.cos(math.radians(arms1.float_time)) * 95 arms1.float_time += 1 # 最低优先级:待机浮动状态(所有上层状态不触发时执行) elif not playerman.rect.colliderect(launch1.rect) and not attacks2 and not pausemove: arms1.y = math.cos(math.radians(arms1.float_time)) * 95 arms1.float_time += 1
注:新增的
arms1.lift_time、arms1.fall_time、arms1.float_time需在Boss类初始化时设置为0,替换原代码中共用的arms1.time、arms1.time3变量,可消除碰撞触发时的Y坐标跳变、显示混乱问题。
内容的提问来源于stack exchange,提问作者Habib Ismail
相关产品推荐
相关产品推荐

