java - 不同帧率游戏版本中LibGDX的差异

标签 java libgdx

我正在开始我的游戏开发冒险,我选择了 LibGDX 作为开始。 我有一个关于速度和帧速率的问题。

float position x=0f;
float velosity v=200f;
float force f=-15f;
public void update(float deltaTime){
    v+=f;
    v*=deltaTime;
    x+=v;
    v*=1/deltaTime;
}

在我的代码中,有一些力使每一帧的速度降低一定量。然后,在同一时间后,以 30FPS 进行游戏的玩家会比以 60FPS 进行游戏的玩家移动得更远,因为力对他的影响次数较少。我对么? 如果是这样,我如何确保两个玩家移动相同的距离?我应该使用一些完全不同的方法吗?

最佳答案

你是对的。如果帧速率不同,您的时间步长不同,因此加速度会有点不可预测。这就是为什么许多游戏使用与游戏帧速率分开运行的固定时间步长。这是一种确保游戏在每台设备上都完全相同的方法。

如果这是一个简单的游戏,竞争性不强,那么您只需确保它保持准确,不一定是确定性的。如果是这种情况,我认为你可以作弊一下,并使用最大时间步长而不是固定时间步长。游戏的玩法不会在任何时候都完全相同,但它会足够准确,以至于没有人会注意到。为此,请设置一些最大增量时间。在游戏的每一帧上,重复调用 update 直到所有 delta 时间用完,但总 delta 时间仍然是准确的。例如:

public static final float MAX_DELTA = 1/50f;
public static final int MAX_UPDATES_PER_FRAME = 3;
private float elapsedTime;

public void render (float deltaTime){
    elapsedTime += deltaTime;
    int updates = 0;
    while (elapsedTime > 0 && updates < MAX_UPDATES_PER_FRAME){
        update(Math.min(MAX_DELTA, elapsedTime));
        elapsedTime = Math.max(0, elapsedTime - MAX_DELTA);
        updates++;
    }

    // drawing
}

所以发生的事情是在 while 循环中,您使用 MAX_DELTA 或更小的时间步长重复更新物理,直到 catch 当前时间。您只需确保 MAX_DELTA 足够小,以确保您的物理效果看起来正确并且无法穿过薄壁。 MAX_UPDATES_PER_FRAME 变量是为了确保当 CPU 峰值导致增量时间太大并且开始越来越落后时,您不会进入“死亡螺旋”。相反,你的游戏会进入一点慢动作,直到 catch 。

这比固定时间步长 ( famously explained here ) 更简单,因为您不必存储两个模拟来在渲染之间进行插值。使用固定的时间步长,上面的代码变为:

public static final float FIXED_TIMESTEP = 1/50f;
public static final int MAX_UPDATES_PER_FRAME = 3;
private float elapsedTime;

public void render (float deltaTime){
    elapsedTime += deltaTime;
    int updates = 0;
    while (elapsedTime >= FIXED_TIMESTEP = && updates < MAX_UPDATES_PER_FRAME){
        update(FIXED_TIMESTEP);
        elapsedTime -= FIXED_TIMESTEP;
        updates++;
    }

    // drawing
}

这会导致难看的卡顿,只能通过保留游戏所有位置数据的两个副本,每帧在它们之间交替,并使用剩余的 elapsedTime 在两者之间进行插值来修复> 获取适合绘制平滑动画的值。非常复杂!

关于java - 不同帧率游戏版本中LibGDX的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40711763/

相关文章:

java - Java 垃圾收集器是否特定于 Major GC?

java - Hibernate - 如何使用整数列表?

java - LibGDX 触摸协调困惑

java - LibGDX Sprite 屏幕未加载图形或加载屏幕

android - libgdx 中的水平滚动 Pane 级别菜单?

java - 将监听器添加到不存在的值

java - 将 Java 应用程序移植到 Android

java - 类之间无法传递数据

java - 在 LibGDX 中组合多种 Material \纹理

java - 在 libGDX 中设置延迟