如何正确使用LibGdx的isAnimationFinished()方法控制动画时序
LibGDX非循环动画播放问题修复
你的三个问题根源完全一致:误用了全局累计的elapsedTime作为动画的stateTime参数。LibGDX的Animation类需要的是从动画启动那一刻开始计时的专属时间,不是游戏启动到现在的总时长。
逐个对应你的问题:
- 动画播放极慢/等待过久无法播放:全局
elapsedTime数值太大,动画直接判定为已完成,或者直接跳到最后几帧,自然看起来慢或不播放 - 动画仅播放一帧就被覆盖:大概率是你误以为被覆盖,实际是动画瞬间完成不再绘制,或者绘制顺序有问题(动画必须在所有地图元素之后画)
下面是具体修复步骤:
- 给动画加专属计时器
在你的类里新增两个变量,分别控制动画的播放状态和运行时间:
private float sparkleTimer = 0f; private boolean isPlayingSparkle = false;
- 触发动画时重置计时器
在拾取物品或关卡完成的逻辑里,启动动画并把计时器归零:
// 比如拾取物品的触发代码里 levelComplete = true; isPlayingSparkle = true; sparkleTimer = 0f; // 必须重置,不然直接用累计时间会导致动画直接结束
- 只在播放时更新计时器
在渲染循环里,只有当动画需要播放时才累加时间,同时判断是否播放完毕:
// 全局elapsedTime继续留着给其他逻辑用 elapsedTime += Gdx.graphics.getDeltaTime(); // 仅播放动画时更新专属计时器 if (isPlayingSparkle) { sparkleTimer += Gdx.graphics.getDeltaTime(); // 动画播放完就关掉状态 if (game.gameAnimations.itemPickUp.isAnimationFinished(sparkleTimer)) { isPlayingSparkle = false; } }
- 调整绘制逻辑(确保层级正确)
把动画绘制放在所有地图元素之后,保证它显示在最上层:
game.batch.begin(); // 先画所有底层元素:地板、墙、门 game.batch.draw(floor,160,160); game.batch.draw(walls,128,160); game.batch.draw(door,370,640); if(!levelComplete){ game.batch.draw(gate,384,640); }else{ // 只有在播放状态时才绘制动画 if(isPlayingSparkle){ game.batch.draw((TextureRegion) game.gameAnimations.itemPickUp.getKeyFrame(sparkleTimer, false),400,500); } } // 如果有角色、道具这类上层元素,要放在动画之前画,避免覆盖动画 game.batch.end();
最后再明确几个关键点:
isAnimationFinished和getKeyFrame接收的stateTime,必须是从动画启动开始的相对时间,不能用全局累计时间getKeyFrame第二个参数传false,确保动画只播放一次,不会循环- 绘制顺序严格遵循“先底后上”,后画的元素会覆盖先画的,所以动画一定要放在所有需要显示在它下面的元素之后
内容的提问来源于stack exchange,提问作者Nicolás Miranda
相关产品推荐
相关产品推荐

