Java Libgdx,物理,加速度和FPS

Java Libgdx,物理,加速度和FPS,java,libgdx,physics,frame-rate,acceleration,Java,Libgdx,Physics,Frame Rate,Acceleration,我正在用Libgdx框架制作一个平台游戏。我想实现跳转到我的角色的能力。我使用简单的公式: speed += acceleration * delta_time r += speed * delta_time 它工作得很好,但只适用于每秒恒定的帧数。FPS越低,我的角色跳跃越低。我不知道这种行为的原因是什么,跳跃的高度应该是相同的:/ 我的代码中有一个片段: delta_time=Gdx.graphics.getDeltaTime(); if(input.getUpArrow()){

我正在用Libgdx框架制作一个平台游戏。我想实现跳转到我的角色的能力。我使用简单的公式:

speed += acceleration * delta_time
r += speed * delta_time
它工作得很好,但只适用于每秒恒定的帧数。FPS越低,我的角色跳跃越低。我不知道这种行为的原因是什么,跳跃的高度应该是相同的:/ 我的代码中有一个片段:

delta_time=Gdx.graphics.getDeltaTime();
if(input.getUpArrow()){
     if(is_in_air==false){
        is_in_air=true;
        speed_y=speed_y_0;
     }
  }

  if(is_in_air==true){
     speed_y-=acceleration*delta_time;
  }
  else{
     speed_y=0;
  }

  x+=speed_x*delta_time;
  y+=speed_y*delta_time;
下面是一个插图(黑点是字符位置):
考虑到您使用的积分器非常简单且高度不准确,这是完全正常的行为。这是很容易做的数学和显示

让我们用1/30秒的时间跨度。当游戏以30 FPS的速度运行时,只有一次更新
speed_y
y
,因此在1/30秒后,新位置
y'
将为:

speed_y' = speed_y - a*dt
y' = y + speed_y'*dt = y + speed_y*dt - a*dt^2
这里
dt
是1/30秒的时间增量

当游戏以每秒60帧的速度运行时,在相同的1/30秒内,将发生两次更新,时间增量缩短两倍,
dt/2

// First update
speed_y' = speed_y - a*(dt/2)
y' = y + speed_y'*(dt/2) = y + speed_y*(dt/2) - a*(dt/2)^2
// Second update
speed_y'' = speed_y' - a*(dt/2) = speed_y - a*dt
y'' = y' + speed_y''*(dt/2) = y + speed_y*dt - 3*a*(dt/2)^2
现在比较两个更新的
y
位置:

  • 在30 FPS时为:
    y+speed\u y*dt-a*dt^2
  • 在60 FPS时为:
    y+速度*y*dt-a*(3/4)*dt^2
显然,在60 FPS时,
y
的新位置将高于30 FPS时的位置,因为减去的值较低

这只影响垂直运动。水平速度是恒定的,无论你用两倍的短时间增量更新一次或两次
x
,因此当你的角色跳跃时,它总是以相同的水平距离移动到它触地的地方,无论FPS是什么

要解决这个问题,你必须仔细观察恒定加速度下的运动方程:

y(t) = y(t=0) + v(t=0)*t - (1/2)*a*t^2
选择
t=0
是任意的,因为物理定律在时移下是不变的,因此可以将
t=0
作为更新间隔的开始,然后
t=delta_time
将给出当前更新后的位置。正确的更新算法如下所示:

x += speed_x*delta_time;
if (is_in_air) {
   y += (speed_y - 0.5*acceleration*delta_time)*delta_time;
   speed_y -= acceleration*delta_time;
}

请注意,
speed_y
应根据运动方程中的值在垂直位置之后更新。getUpArrow”的作用是什么?什么时候返回true/false?当按下键盘上的up键时返回true。非常感谢您的解释。现在一切正常。