如何使LibGDX动作moveTo()以曲线的形式从一个点动画到另一个点?

时间:2018-04-17 11:59:05

标签: java animation libgdx interpolation scene2d

我正在开发LibGDX中的一个项目,我正在为一些精灵使用 Scene2D actor。在这方面,我有一个精灵,它在屏幕上的某个地方产生,需要移动到屏幕上的另一个位置。为此,我使用动作中的moveTo(xPos, yPos, duration, interpolation)方法来制作移动动画。

然而,当我使用这种方法时,演员像我告诉它一样移动,但它只是从A点到B的直线移动。我尝试了几个插值选项,如圆插值等,但它似乎只会影响动画线的速度。

所以现在我的问题是:如何让我的动画制作一条平滑的曲线(见图),从A到B? enter image description here

我目前正在使用此代码制作动作动画:

adultCustomerPointActor.addAction(Actions.sequence(
    Actions.moveTo(300, 200, 2f, Interpolation.circle)
));

先谢谢你的帮助:)

1 个答案:

答案 0 :(得分:1)

这是一个几何问题。使用向量,找到两点之间的点:

vec1.set(bx, by).sub(ax, ay).scl(0.5f).add(ax, ay);

从点之间的向量中获取另一个90或270的向量:

vec2.set(bx, by).sub(ax, ay).rotate90().add(vec1);

可以缩放此vec2以调整弧的极端曲率。如果你不管它,你将有一个四分之一圈。您也可以将其缩放为负值以反转曲率。

然后将第二个向量添加到第一个向量中以找到弧的中心点,我们可以将其称为C点。

vec1.set(bx, by).sub(vec2); // CB
vec3.set(ax, ay).sub(vec2); // CA
float angle = vec1.angle(vec3);

现在你需要一个从C点指向A点的矢量。你将旋转这个矢量直到它到达B点。所以你需要CA和CB之间的角度。

所以这是一个非常简单的类来实现这一点。它尚未考虑您是否希望弧线上升或下降,以及是否要缩放它看起来的极端程度。您可以使用getter / setter将它们添加为附加参数。我没有测试过,所以可能需要一些调试。

public class ArcToAction extends MoveToAction {
    private float angle;
    private final Vector2 vec1 = new Vector2(), vec2 = new Vector2(), vec3 = new Vector2();

    @Override
    protected void begin () {
        super.begin();
        float ax = target.getX(getAlignment()); // have to recalculate these because private in parent
        float ay = target.getY(getAlignment());
        vec1.set(getX(), getY()).sub(ax, ay);
        vec2.set(vec1).rotate90();
        vec1.scl(0.5f).add(ax, ay);
        vec2.add(vec1);
        vec1.set(bx, by).sub(vec2); // CB
        vec3.set(ax, ay).sub(vec2); // CA
        angle = vec1.angle(vec3);
    }

    protected void update (float percent) {
        if (percent >= 1){
            target.setPosition(getX(), getY(), getAlignment());
            return;
        }

        vec1.set(vec3).rotate(percent * angle);
        target.setPosition(vec1.x, vec1.y, getAlignment());
    }

}

如果您想支持自动池,可以添加如下方法:

static public ArcToAction arcTo (float x, float y, float duration, Interpolation interpolation) {
    ArcToAction action = Actions.action(ArcToAction .class);
    action.setPosition(x, y);
    action.setDuration(duration);
    action.setInterpolation(interpolation);
    return action;
}