相机应顺畅地跟随特定点

Camera should smoothly follow a specific point

在我的游戏(基于 LWJGL 的 3D 游戏)中,我走在一个体素(块)世界中。角色上下移动的速度非常快,所以我希望相机能顺畅地跟随角色。我尝试了插值,但我必须插值的点一直在变化,因为角色没有立即采取步骤(大约 5-8 帧)。这会导致一些看起来不太好的晃动。有没有办法做得更好?

问候

cameraYPosition = MathHelper.sinerp(cameraYCorrectionPoint, player.y, ((float)glfwGetTime() - cameraYCorrectionTime) * (1/cameraYCorrectionDuration));

这是决定性的线。 cameraYCorrectionPoint 是相机开始插值的点,而 player.y 是插值的位置(显然可以改变每一帧)。另一部分是计算经过的时间并将其放大,使其范围从 0 到 1。

这并没有真正起作用,因为在初始插值完成之前位置可能会再次更改,从而导致难看的插值。那么我能做些什么来获得更好的方法呢?

这是其余代码,但我认为这不会有太大帮助:

if(cameraYPosition == Float.MIN_VALUE) cameraYPosition = player.y;

    if(player.y != cameraYPosition) {
        if(cameraYCorrectionPoint == Float.MIN_VALUE) {
            cameraYCorrectionPoint = cameraYPosition;
            cameraYCorrectionTime = (float)glfwGetTime();
        }

        if(cameraYCorrectionTime <= glfwGetTime()) {
            float absoluteDistance = cameraYCorrectionPoint - player.y;

            float relativeDistance = cameraYPosition - player.y;

            if(glfwGetTime() - cameraYCorrectionTime <= cameraYCorrectionDuration) {
                cameraYPosition = MathHelper.sinerp(cameraYCorrectionPoint, player.y, ((float)glfwGetTime() - cameraYCorrectionTime) * (1/cameraYCorrectionDuration));
            }
            else {
                cameraYPosition = player.y;
            }

            lastPlayerY = player.y;

            if(absoluteDistance > 0 && cameraYPosition < player.y || absoluteDistance < 0 && cameraYPosition > player.y) {
                cameraYCorrectionDuration = cameraYBaseCorrectionDuration;

                if(relativeDistance < 0 && cameraYPosition - player.y > 0 || relativeDistance > 0 && cameraYPosition - player.y < 0) {
                    cameraYPosition = player.y;
                }
                else {
                    cameraYCorrectionPoint = cameraYPosition;
                }
            }
        }
    }
    else {
        cameraYCorrectionDuration = cameraYBaseCorrectionDuration;

        cameraYCorrectionPoint = Float.MIN_VALUE;
    }

还有我的插值代码:

package main;

public class MathHelper {
    public static float hermite(float start, float end, float value) {
        return lerp(start, end, value * value * (3.0f - 2.0f * value));
    }

    public static float sinerp(float start, float end, float value) {
        return lerp(start, end, (float)Math.sin(value * Math.PI * 0.5f));
    }

    public static float coserp(float start, float end, float value) {
        return lerp(start, end, 1.0f - (float)Math.cos(value * Math.PI * 0.5f));
    }

    public static float lerp(float start, float end, float value) {
        return ((1.0f - value) * start) + (value * end);
    }
}

您可以对相机进行一些不同的建模。将位置拆分为当前位置和目标位置。当您要移动相机时,只需移动目标位置即可。然后,每一帧,更新当前相机位置以更接近目标位置。我对以下更新有很好的经验:

factor = f ^ t
currentCamera = factor * currentCamera + (1 - factor) * targetCamera

f 是一个因素,可让您选择相机反应的即时程度。较高的值将导致非常缓慢的运动,值为 0 将使相机准确地跟随其目标。 t 是自上次更新调用以来的时间。如果 t 以毫秒为单位,则 f 的值应介于 0.95 和 0.99 之间。