Libgdx,物理,加速和FPS

Yae*_*aem 2 java physics frame-rate acceleration libgdx

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

speed += acceleration * delta_time
r += speed * delta_time
Run Code Online (Sandbox Code Playgroud)

它运行良好,但仅适用于每秒恒定帧数.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;
Run Code Online (Sandbox Code Playgroud)

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

Hri*_*iev 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

现在比较两个更新的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
Run Code Online (Sandbox Code Playgroud)

选择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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,speed_y应根据运动方程中的值在垂直位置更新.