我正在开始我的游戏开发冒险,我选择了 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/