Как сохранить высоту прыжка при использовании дельта-времени?

Я использую дельта-время, чтобы сделать частоту кадров моей программы независимой.
Однако я не могу получить высоту прыжка, она будет одинаковой, персонаж всегда прыгает выше при более низкой частоте кадров.

Переменные:

const float gravity = 0.0000000014f;
const float jumpVel = 0.00000046f;
const float terminalVel = 0.05f;
bool readyToJump = false;
float verticalVel = 0.00f;

Логический код:

if(input.isKeyDown(sf::Keyboard::Space)){
if(readyToJump){
verticalVel = -jumpVel * delta;
readyToJump = false;
}
}

verticalVel += gravity * delta;
y += verticalVel * delta;

Я уверен, что дельта-время правильное, потому что персонаж движется горизонтально хорошо.

Как заставить моего персонажа прыгать одинаково, независимо от частоты кадров?

5

Решение

Формула для расчета новой позиции:

position = initial_position + velocity * time

С учетом силы тяжести, которая уменьшает скорость в зависимости от функции:

velocity = initial_velocity + (gravity^2 * time)

ПРИМЕЧАНИЕ: сила тяжести в этом случае не совпадает с силой тяжести.
Окончательная формула становится:

position = initial_position + (initial_velocity + (gravity^2 * time) * time

Как видно из приведенного выше уравнения, на initial_position и initial_velocity не влияет время. Но в вашем случае вы фактически устанавливаете начальную скорость, равную -jumpVelocity * delta,

Чем ниже частота кадров, тем больше значение delta будет, и, следовательно, персонаж будет прыгать выше. Решение состоит в том, чтобы изменить

if(readyToJump){
verticalVel = -jumpVel * delta;
readyToJump = false;
}

в

if(readyToJump){
verticalVel = -jumpVel;
readyToJump = false;
}

РЕДАКТИРОВАТЬ:

Вышесказанное должно дать довольно хорошую оценку, но это не совсем правильно. При условии, что p(t) позиция (в данном случае высота) после времени t, тогда скорость определяется v(t) = p'(t)', and the acceleration is given bya (t) = v ‘(t) = p’ ‘(t) `. Поскольку мы знаем, что ускорение является постоянным; т.е. под действием силы тяжести мы получаем следующее:

a(t) = g
v(t) = v0 + g*t
p(t) = p0 + v0*t + 1/2*g*t^2

Если мы теперь посчитаем p(t+delta)-p(t)Т.е. при смене позиции от одного экземпляра во времени к другому мы получаем следующее:

p(t+delta)-p(t) = p0 + v0*(t+delta) + 1/2*g*(t+delta)^2 - (p0 + v0*t + 1/2*g*t^2)
= v0*delta + 1/2*g*delta^2 + g*delta*t

Оригинальный код не учитывает возведение в квадрат delta или дополнительный срок g*delta*t*, Более точным подходом было бы сохранить увеличение дельты, а затем использовать формулу для p(t) дано выше.

Образец кода:

const float gravity = 0.0000000014f;
const float jumpVel = 0.00000046f;
const float limit = ...; // limit for when to stop jumping

bool isJumping = false;
float jumpTime;

if(input.isKeyDown(sf::Keyboard::Space)){
if(!isJumping){
jumpTime = 0;
isJumping = true;
}
else {
jumpTime += delta;
y = -jumpVel*jumpTime + gravity*sqr(jumpTime);
// stop jump
if(y<=0.0f) {
y = 0.0f;
isJumping = false;
}
}
}

ПРИМЕЧАНИЕ: я не скомпилировал и не протестировал код выше.

6

Другие решения

Под «дельта-временем» вы подразумеваете переменные временные шаги? Как в каждом кадре вы вычисляете временной шаг, который может полностью отличаться от предыдущего?

Если так, НЕ.

Прочитай это: http://gafferongames.com/game-physics/fix-your-timestep/

TL; DR: использовать фиксированные временные шаги для внутреннего состояния; интерполировать кадры, если это необходимо.

0

По вопросам рекламы [email protected]