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

如何让LibGDX Actions的moveTo()实现曲线动画移动?

嘿,我之前在LibGDX项目里也遇到过这个需求——默认的moveTo只能走直线,哪怕换插值器也只是改变移动的速度曲线,没法改变路径形状对吧?给你几个靠谱的实现曲线移动的方案:

实现LibGDX Scene2D Actor曲线移动的几种方案

1. 用内置的PathAction配合贝塞尔曲线(最推荐)

LibGDX已经内置了路径移动的Action,直接用Bezier或CatmullRomSpline定义曲线路径,再交给PathAction就能搞定。

比如用二阶贝塞尔曲线(需要1个控制点来弯曲路径):

// 定义起点、控制点、终点
Vector2 startPos = new Vector2(100f, 100f); // 你的精灵初始位置
Vector2 controlPoint = new Vector2(300f, 500f); // 控制曲线弯曲方向的点
Vector2 endPos = new Vector2(500f, 100f); // 目标位置

// 创建贝塞尔路径
Bezier<Vector2> bezierPath = new Bezier<>(startPos, controlPoint, endPos);

// 生成路径移动Action,duration是总时长,插值器控制速度变化
PathAction curveMoveAction = Actions.path(bezierPath, 2f, Interpolation.smooth);

// 给你的精灵Actor添加这个动作
yourSpriteActor.addAction(curveMoveAction);

如果需要更平滑的多段曲线,可以用Catmull-Rom样条,它会自动把多个点连成平滑曲线:

// 定义一系列路径点(精灵会沿着这些点连成的平滑曲线移动)
Vector2[] waypoints = {
    new Vector2(100f, 100f),
    new Vector2(200f, 400f),
    new Vector2(400f, 300f),
    new Vector2(500f, 100f)
};
CatmullRomSpline<Vector2> splinePath = new CatmullRomSpline<>(waypoints, false);

// 生成样条移动Action
PathAction splineMoveAction = Actions.path(splinePath, 3f, Interpolation.linear);
yourSpriteActor.addAction(splineMoveAction);

2. 自定义TemporalAction实现自定义曲线

如果内置的路径满足不了你的需求(比如需要特殊的曲线公式),可以自己写一个继承TemporalAction的自定义动作,手动计算每帧的位置。

比如实现一个二阶贝塞尔曲线的自定义Action:

public class CustomBezierMoveAction extends TemporalAction {
    private final Vector2 start, control, end;
    private final Vector2 tempVec = new Vector2();

    // 构造方法传入起点、控制点、终点和时长
    public CustomBezierMoveAction(Vector2 start, Vector2 control, Vector2 end, float duration) {
        this.start = start;
        this.control = control;
        this.end = end;
        setDuration(duration);
    }

    @Override
    protected void update(float percent) {
        // 二阶贝塞尔曲线公式:B(t) = (1-t)²*P0 + 2*(1-t)*t*P1 + t²*P2
        // percent是当前进度(0到1)
        tempVec.set(start).scl((1 - percent) * (1 - percent));
        tempVec.add(control.cpy().scl(2 * (1 - percent) * percent));
        tempVec.add(end.cpy().scl(percent * percent));
        
        // 设置Actor的位置
        target.setPosition(tempVec.x, tempVec.y);
    }
}

// 使用的时候直接创建并添加到Actor
yourSpriteActor.addAction(new CustomBezierMoveAction(startPos, controlPoint, endPos, 2f));

为什么之前的moveTo不行?

你之前用的moveTo(x,y,duration,interpolation),这里的插值器只控制移动的速度变化(比如先快后慢,或者先慢后快),但本质上还是在起点和终点的直线上移动,所以不管换什么插值器,路径都是直线。要走曲线,必须基于路径来计算每帧的位置,而不是简单的两点线性插值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:19:43