OpenGL中的基本重力实现

时间:2019-03-27 08:58:07

标签: c++ game-physics

我正在尝试在OpenGL游戏中实现跳跃。我的左右“速度”和“摩擦”效果很好,但我无法使跳跃动作顺畅。玩家被困在空中:

void keyboard() {
    //Move Left
    if (GetAsyncKeyState(keyA)) {
        playerVelX -= 3;
    }
    //Move Right
    if (GetAsyncKeyState(keyD)) {
        playerVelX += 3;
    }
    //Jump
    if (GetAsyncKeyState(keySpace)) {
        playerVelY += 3;
    }
}

void position() {
    //Move on x and y axis
    playerX += playerVelX;
    playerY += playerVelY;

    //Slow down respective axes
    playerVelX *= friction;
    playerVelY *= gravity;
}

while(gameRunning) {
    keyboard();
    position();
}

我想我已经看了太久了。有人有这样的重力实现经验吗?谢谢

2 个答案:

答案 0 :(得分:1)

您施加重力的公式是错误的。请记住,F=m.av=v_0+ a*tx=x_0 +v_0*t + 0.5*a*t^2。但是通常的方法是使用欧拉方法进行数值积分:

gravity=9.81;
velocity+=gravity*deltaT;
position+=velocity*deltaT;

在您的代码中,它看起来像:

playerVelX *= friction;
playerVelY -= gravity;//If Y point up, so gravity acts against that.

playerX += playerVelX;
playerY += playerVelY;

如果要确定性和稳定的仿真(应该这样做),则需要具有deltaTime-自上次更新以来经过了多少时间。请参阅这篇出色的文章Fix Your Timstep!。同样,上面的代码即使在没有跳跃的情况下也不断施加重力,因此请注意这一点。

答案 1 :(得分:0)

总结所有不准确之处:

  1. 明显的错误m * dv/dt = -m * g如此dv = -g * dt如此playerVelY -= gravity * dt
  2. 在跳跃中,进一步的排斥是不可能的,所以

    if (GetAsyncKeyState(keySpace) && (playerY <= groundLevel)) {
        playerVelY += 3;
    }
    
  3. 如果玩家在地面上,重力就不起作用。

    if (playerY < groundLevel)
    {
       playerY = groundLevel;
       playerVelY = 0; 
    }
    

    考虑反作用力更现实。

  4. 您的模型playerVelX *= friction;对应于粘性摩擦。玩家将永远不会停止。您确定需要粘性而不是干摩擦吗?

  5. dt应该定义为两次更新之间的实时时间,否则,结果将取决于当前的刷新率。您需要类似

    的东西
    void position() {
       static double lastTime = getCurrTime();
       double currTime = getCurrTime();
       double dt = currTime - lastTime;
    
       playerX += playerVelX * dt;
       playerY += playerVelY * dt;
    
       if (playerY < groundLevel)
       {
           playerY = groundLevel;
           playerVelY = 0; 
       }
    
       //Slow down respective axes
       playerVelX *= exp(-friction * dt); // playerVelX *= (1 - friction * dt) for small dt
       playerVelY -= gravity * dt;
    
       lastTime = currTime;
    }