【问题标题】:LibGDX differences in games versions with different framerate不同帧率游戏版本的LibGDX差异
【发布时间】:2016-11-21 02:04:30
【问题描述】:

我从游戏开发开始我的冒险,我选择了 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 播放的玩家移动得更远,因为力会影响他的次数更少。我对么? 如果是这样,我如何确保两个玩家移动相同的距离?我应该使用一些完全不同的方法吗?

【问题讨论】:

    标签: java libgdx


    【解决方案1】:

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

    如果这是一款简单的游戏,竞争不激烈,那么您只需要确保它保持准确,不一定确定性。如果是这种情况,我认为您可以作弊,并使用最大时间步长而不是固定时间步长。游戏不会在任何时候都以完全相同的方式进行,但它会足够准确,以至于没有人会注意到。为此,请设置一些最大增量时间。在游戏的每一帧上,重复调用 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 或更小的时间步长重复更新物理直到赶上当前时间。你只需要确保MAX_DELTA 足够小以确保你的物理看起来正确并且你不能穿过薄壁。 MAX_UPDATES_PER_FRAME 变量是为了确保当 CPU 峰值导致增量时间过大并且开始越来越落后时,您不会进入“死亡螺旋”。相反,您的游戏会进入一些慢动作直到赶上。

    这比固定时间步长 (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 来解决适合绘制流畅的动画。很复杂!

    【讨论】:

      【解决方案2】:

      您可以将移动与增量时间值(帧之间的时间)相乘,以使其与帧速率无关。使用 libgdx 可以使用以下方法:

      Gdx.graphics.getDeltaTime();
      

      这是一个简单的例子:

         x += 500 * Gdx.graphics.getDeltaTime();
      

      【讨论】:

      • 这就是我在我的问题中所做的,我将速度乘以增量时间并将其添加到当前位置。但是当速度不是恒定的并且在每一帧中都在降低时,那么低 fps 的玩家会比高 fps 的玩家移动得更远,不是吗?
      • 是的,他在每一帧都移动得更远,但是 fps 较高的玩家移动的次数比 fps 较低的玩家移动的次数多。因此,每个移动或多或少相同的距离
      • 根据我在 1 秒后的计算,如果他们都按一次前进按钮,那么 1 fps 的玩家将比 30 fps 的玩家多走大约 40 个单位。 40 是相当大的差异,我不希望用户利用这一点并以较低的 fps 获得更高的分数
      猜你喜欢
      • 1970-01-01
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      • 2015-07-22
      • 2021-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多