我正在尝试在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();
}
我想我已经看了太久了。有人有这样的重力实现经验吗?谢谢
答案 0 :(得分:1)
您施加重力的公式是错误的。请记住,F=m.a
,v=v_0+ a*t
,x=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)
总结所有不准确之处:
m * dv/dt = -m * g
如此dv = -g * dt
如此playerVelY -= gravity * dt
在跳跃中,进一步的排斥是不可能的,所以
if (GetAsyncKeyState(keySpace) && (playerY <= groundLevel)) {
playerVelY += 3;
}
如果玩家在地面上,重力就不起作用。
if (playerY < groundLevel)
{
playerY = groundLevel;
playerVelY = 0;
}
考虑反作用力更现实。
您的模型playerVelX *= friction
;对应于粘性摩擦。玩家将永远不会停止。您确定需要粘性而不是干摩擦吗?
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;
}