相机应顺畅地跟随特定点
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 之间。
在我的游戏(基于 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 之间。