GameMaker兔子跳跃动画异常求助:落地无法切换至Idle Sprite
兔子跳跃动画问题排查与修复
需求说明
我需要用3个精灵实现兔子跳跃动画:
spr_conejo_idle:2帧spr_conejo_airbourne_up:5帧(前4帧用于起跳,vsp < 0时冻结最后一帧)spr_conejo_airbourne_down:4帧(vsp > 0时显示第1帧,落地时播放最后3帧)
预期逻辑:
角色跳跃时切换至
spr_conejo_airbourne_up,冻结最后一帧直到开始下落(vsp <= 0);下落时切换至spr_conejo_airbourne_down,冻结第1帧直到垂直碰撞墙体,随后播放落地动画并最终切换至Idle精灵。
当前问题
- 角色落地后无法切换至
spr_conejo_idle,持续循环spr_conejo_airbourne_down - 偶尔在空中时,精灵会短暂切换至Idle帧
现有代码
CREATE事件
hp = 1; hsp = 0; vsp = 0; grv = 0.3; maxIdle = 360; onFloor = true; hitfrom = 0; size = 1;
STEP事件
vsp += grv; maxIdle--; if (place_meeting(x,y+1,obj_wall)){onFloor = true;}else{onFloor = false;} if (onFloor){if (maxIdle <= 0){maxIdle = random_range(60, 360);vsp = -6;onFloor = false;hsp = random_range(-3,3);}} if(!onFloor){if (sign(vsp) < 0) {image_speed = 1;sprite_index = spr_conejo_airbourne_up;}else{image_speed = 0;sprite_index = spr_conejo_airbourne_down;}} else{image_speed = 1;vsp = 0;hsp = 0;} if (place_meeting(x+hsp,y,obj_wall)){while (!place_meeting(x+sign(hsp),y,obj_wall)){x += sign(hsp);}hsp = 0;} x += hsp; if (place_meeting(x,y+vsp,obj_wall)){while (!place_meeting(x,y+sign(vsp),obj_wall)){y += sign(vsp);}vsp = 0;} y += vsp; if (hsp != 0) image_xscale = sign(hsp)*-1;
ANIMATION END事件
if (sprite_index == spr_conejo_airbourne_up) image_speed = 0; if (sprite_index == spr_conejo_airbourne_down) sprite_index = spr_conejo_idle;
问题分析与修复方案
核心问题点
- 落地精灵切换逻辑缺失:
onFloor为true时仅重置速度,未明确设置Idle精灵,导致落地后停留在spr_conejo_airbourne_down,且无法触发Animation End事件完成切换。 - 下落动画控制错误:下落阶段直接将
image_speed设为0,落地后无法播放最后3帧落地动画,自然触发不了切换Idle的逻辑。 - 状态判断时机偏差:先判断地面状态再处理移动,移动后实际落地但精灵切换逻辑已执行,导致空中误切Idle。
修复后的代码
修改后的STEP事件
vsp += grv; maxIdle--; // 先处理水平移动 if (place_meeting(x+hsp,y,obj_wall)){ while (!place_meeting(x+sign(hsp),y,obj_wall)){ x += sign(hsp); } hsp = 0; } x += hsp; // 处理垂直移动并判断落地状态 var wasOnFloor = onFloor; onFloor = place_meeting(x,y+1,obj_wall); if (place_meeting(x,y+vsp,obj_wall)){ while (!place_meeting(x,y+sign(vsp),obj_wall)){ y += sign(vsp); } vsp = 0; // 从空中刚落地时,触发落地动画 if (!wasOnFloor && onFloor){ sprite_index = spr_conejo_airbourne_down; image_speed = 1; image_index = 1; // 直接跳至落地动画第2帧,播放最后3帧 } } y += vsp; // 状态与精灵切换逻辑 if (onFloor){ vsp = 0; hsp = 0; // Idle状态下处理自动跳跃 if (sprite_index == spr_conejo_idle){ image_speed = 1; if (maxIdle <= 0){ maxIdle = random_range(60, 360); vsp = -6; onFloor = false; hsp = random_range(-3,3); } } }else{ // 空中上升阶段 if (vsp < 0){ if (sprite_index != spr_conejo_airbourne_up){ sprite_index = spr_conejo_airbourne_up; image_speed = 1; } // 播放完上升动画后冻结最后一帧 if (image_index >= sprite_get_number(spr_conejo_airbourne_up)-1){ image_speed = 0; } } // 空中下落阶段(未落地) else{ if (sprite_index != spr_conejo_airbourne_down){ sprite_index = spr_conejo_airbourne_down; image_speed = 0; image_index = 0; // 冻结第一帧 } } } // 方向翻转 if (hsp != 0) image_xscale = sign(hsp)*-1;
修改后的ANIMATION END事件
if (sprite_index == spr_conejo_airbourne_down){ sprite_index = spr_conejo_idle; image_speed = 1; image_index = 0; }
修复说明
- 调整移动与状态判断顺序:先处理移动再判断地面状态,确保
onFloor的判断基于最新位置,避免空中误判落地。 - 落地动画触发逻辑:角色从空中落地时,主动切换到落地精灵并设置从第2帧开始播放,开启动画速度确保落地动画完整播放。
- 上升动画冻结逻辑:上升阶段播放完所有帧后再冻结,替代原Animation End的冻结逻辑,避免冲突。
- Idle状态明确切换:仅当落地动画播放完成(触发Animation End)时,才切换到Idle精灵,保证落地动画播放完毕后再回到待机状态。
内容的提问来源于stack exchange,提问作者user16608259
相关产品推荐
相关产品推荐

