2

我正在 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;

这是一个插图(黑点是字符位置):http: //i.imgur.com/tfSTM.jpg

4

1 回答 1

6

鉴于您使用的积分器非常简单且非常不准确,这是完全正常的行为。做数学并证明这一点很容易。

让我们取一个 1/30 秒的时间跨度。当游戏以 30 FPS 运行时,只有一次更新speed_yy,因此在 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 FPS 运行时,在相同的 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_y*dt - a*dt^2
  • 在 60 FPS 时,它是:y + speed_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应根据运动方程中的值在垂直位置之后更新。

于 2013-01-11T14:03:54.203 回答