java - 通用补间引擎/LibGDX:模型会按顺序丢失补间之间的变换和旋转

标签 java libgdx tween translate-animation rotateanimation

我正在开发3D游戏,并试图正确设置角色移动。交互很简单,屏幕上只有一个模型,用户单击屏幕上的一个点,模型旋转以面对所单击的点(现在该模型是一个带有眼睛的小鬼,所以眼睛转为面对被点击的对象点),并且一旦面对该点,模型便会在那里移动。

我使用自己编写的一些代码进行了此工作,但是动画并不流畅,并且模型经常会超出目标位置,然后向后或向前晃动。之前,我只在2D动画上使用Universal Tween引擎,但决定尝试一下。它解决了混蛋问题,并且旋转和变换两个文件都可以正常工作,但是我无法让它们按顺序一起工作。

如果我仅启用旋转模型的代码,则可以正常工作(嗯,几乎可以,在确定某些角度的顺时针或逆时针旋转时有些奇怪,但这是稍后要解决的另一个问题):我单击一个位置,模型旋转以面对它,并保留新的旋转,直到下次单击,然后转向该位置。与仅启用翻译的情况相同:我单击一个点,模型移至该点并保留其新的翻译,直到再次单击,然后移至该位置,依此类推。

同时启用平移和旋转功能时,我遇到了问题。模型将首先旋转以面对点击点,然后设置回初始旋转,然后移动到点击点。在随后的点击中,模型将首先返回其初始平移,然后旋转以面对点击点(实际上是点击点相对于重新初始化位置的位置),然后移动到点击点。

我已经尝试过使用回调来重新排列代码,将新的平移和旋转缓存到游戏模型类的成员中,然后在开始补间之前将set()与它们的值一起使用,但是没有任何效果。

这是我的TweenAccessor中的相关代码:

public class GameModelTweenAccessor implements TweenAccessor<DynamicModel> {    
    public int getValues(DynamicModel target, int tweenType, float[] returnValues) {
        trans = target.model.transform.getTranslation(trans);
        switch (tweenType) {
            ...
            case POSITION_XYZ:
                returnValues[0] = trans.x;
                returnValues[1] = trans.y;
                returnValues[2] = trans.z;
                return 3;
            case ROTATION:
                axisVec = new Vector3();
                angle = target.model.transform.getRotation(new Quaternion()).getAxisAngle(axisVec) * axisVec.nor().y;
                returnValues[0] = angle;
                return 1;
            ...
        }

    }

    public void setValues(DynamicModel target, int tweenType, float[] newValues) {
        trans = target.model.transform.getTranslation(trans);
        switch (tweenType) {
            ...
            case POSITION_XYZ:
                target.model.transform.setToTranslation(newValues[0], newValues[1], newValues[2]);
                break;
            case ROTATION:
                target.model.transform.setToRotation(Vector3.Y, newValues[0]);
                break;
            ...
        }
    }
}


这是开始时间轴和补间的代码(在this file中):

Timeline.createSequence()
    .push(Tween.to(screen.ghost, GameModelTweenAccessor.ROTATION, Math.abs(angle - newRotation) / 200)
        .target(newRotation)
        .ease(TweenEquations.easeNone))
    .push(Tween.to(screen.ghost, GameModelTweenAccessor.POSITION_XYZ, duration).
        target(intersection.x, intersection.y, intersection.z)
        .ease(TweenEquations.easeNone))
    .start(screen.ghostManager);


谁能指出我的解决方案?

编辑:
似乎在每个补间完成时设置的变换将在另一个补间完成后重置为0。这些是getValuessetValuesTweenAccessor函数的值的日志:

Get Rot: 0.0

Get Trans: x: 0.0          y: 0.0          z: 0.0

Get Rot: 0.0

Get Trans: x: 0.0          y: 0.0          z: 0.0

Get Rot: 0.0

Set Rot: 9.598349
Set Rot: 9.814415
Set Rot: 10.052449
...
Set Rot: 39.99417
Set Rot: 43.397423
Set Rot: 46.62333

Get Trans: x: 0.0          y: 0.0          z: 0.0

Set Trans: x: 0.0012489144 y: 0.0          z: 0.001180494
Set Trans: x: 0.024489587  y: 0.0          z: 0.023147952
Set Trans: x: 0.04921494   y: 0.0          z: 0.04651875
...
Set Trans: x: 6.4197707    y: 0.0          z: 6.06807
Set Trans: x: 6.444479     y: 0.0          z: 6.091425
Set Trans: x: 6.453598     y: 0.0          z: 6.1000443

Get Rot: 0.0

Get Trans: x: 6.453598     y: 0.0          z: 6.1000443

Get Rot: 0.0

Get Trans: x: 6.453598     y: 0.0          z: 6.1000443

Get Rot: 0.0

Set Rot: 3.4318955
Set Rot: 6.795984
Set Rot: 10.0074415
...
Set Rot: 156.79567
Set Rot: 159.99591
Set Rot: 162.38742

Get Trans: x: 0.0          y: 0.0          z: 0.0

Set Trans: x: 0.03550978   y: 3.836017E-8  z: 0.021066409
Set Trans: x: 0.15527377   y: 1.6773768E-7 z: 0.092117175
...
Set Trans: x: 6.848614     y: 7.3983565E-6 z: 4.062985
Set Trans: x: 6.961268     y: 7.5200533E-6 z: 4.129818
Set Trans: x: 7.0624847    y: 7.6293945E-6 z: 4.189865

Get Rot: 0.0

Get Trans: x: 7.0624847    y: 7.6293945E-6 z: 4.189865

Get Rot: 0.0

Get Trans: x: 7.0624847    y: 7.6293945E-6 z: 4.189865

Get Rot: 0.0

Set Rot: -3.2620814
Set Rot: -6.8205137
Set Rot: -9.834579
...
Set Rot: -76.57533
Set Rot: -79.91388
Set Rot: -80.610855

Get Trans: x: 0.0          y: 0.0          z: 0.0

Set Trans: x: 0.01940876   y: 0.0          z: 0.033669088
Set Trans: x: 0.04174851   y: 0.0          z: 0.07242267
Set Trans: x: 0.06332677   y: 0.0          z: 0.109855264
...
Set Trans: x: 2.7853239    y: 0.0          z: 4.8318033
Set Trans: x: 2.808029     y: 0.0          z: 4.8711905
Set Trans: x: 2.827034     y: 0.0          z: 4.9041595


在补间开始之前,每种补间类型(平移和旋转)都会调用getValues两次。此时,翻译值仍然是在最后翻译补间结束时设置的值。不过,旋转值已重新设置为0(我猜是由于对setValues进行下一轮旋转调用的结果)。

然后,多次调用setValues进行旋转,直到达到目标旋转。这(除了重置轮换外)按我期望和希望的那样工作。但是,在getRotation调用之后,转换将设置回0,0,0,但不会通过调用setValues进行转换(没有日志记录)。然后通过几次setValues调用将翻译动画化为目标。

此后,再次单击将重新开始循环,并再次调用getValues两次以进行旋转和平移。平移具有在最后一个setValues中最后一次调用Timeline时设置的值,但是直到旋转(返回0)经过其补间为止。

getValues的4个调用可能是某些东西。我不确定在我的设置中什么会导致Timeline会在补间开始之前获取转换的值,如果它们应按在Timeline中的顺序执行的话。我也不确定为什么每个补间调用getValues两次,但是在补间过程中Tween引擎会两次调用它并不是不可行的。

我很确定我使用的LibGDX的平移/旋转功能很好,它们“粘”在模型上,并且我使用的翻译与非Tween-Engine版本相同。旋转相似,但功能不同。

不过,在第二次转换期间要更改的Y值值得​​研究。

最佳答案

因此,该解决方案与Universal Tween Engine或实现方式无关。只是我对LibGDX中的矩阵转换功能的了解不多。对setToRotation的调用将重置变换矩阵,然后仅应用旋转,从而将先前平移归零。 setToTranslation相同,导致旋转丢失。

对于翻译,我改用setTranslation,并且旋转不会丢失。我认为没有类似的旋转功能(使用rotate会引起各种问题),所以我得到一个新的Vector3,其中存储了模型的位置,然后应用setToRotation,然后设置平移到新向量。这是TweenAccessor中的更新代码:

public void setValues(DynamicModel target, int tweenType, float[] newValues) {
    trans = target.model.transform.getTranslation(trans);
    switch (tweenType) {
        ...
        case POSITION_XYZ:
            target.model.transform.setTranslation(newValues[0], newValues[1], newValues[2]);
            break;
        case ROTATION:
            // store the position
            Vector3 position = target.model.transform.getTranslation(new Vector3());
            // then set the rotation and reset the translation
            target.model.transform.setToRotation(Vector3.Y, newValues[0]).setTranslation(position);
            break;
        default:
            assert false;
            break;
    }
}

关于java - 通用补间引擎/LibGDX:模型会按顺序丢失补间之间的变换和旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27770920/

相关文章:

java - 有效的 Java item 1 适用性与 TDD 和依赖注入(inject)

java - JSF - JBoss 集群上的 SessionExpirationPhaseListener

java - 延迟将对象移动到另一个对象

javascript - tween control.reset() of trackball controls js 不工作

java - 如何在Libgdx中安装Tween引擎(Eclipse项目)

r - gganimate 根据时间对多条路径进行动画处理

java - 如何使用 document.ready 函数调用 servlet 类

Java Tic Tac Toe with ImageIcons - 改进建议

android - 在 libgdx 中设置世界边界

java - libGDX:根据用户的输入更改 PNG 的颜色