Переменные временные шаги и гравитация / трение - PullRequest
0 голосов
/ 19 декабря 2011

Я пытаюсь скопировать логику физического движка Sonic , который был написан для системы с фиксированным временным шагом (60 FPS), с переменным возрастом (Slick2D, если быть точным).

В оригинале после нажатия кнопки прыжка velocity.y игрока устанавливается на -6,5, а каждый тик 0,21875 добавляется к velocity.y для моделирования силы тяжести.

Каждый раз, когда вызывается мое обновление логики, передается параметр дельта времени, указывающий, сколько миллисекунд прошло.Если прошло больше миллисекунд, чем я ожидал, тогда я повторяю логику обновления, пропуская «внутреннюю дельту», которая не больше 1 или меньше, если мы имеем дело с «остатком» целевого кадра.

Например, если мы ожидаем, что кадр займет 16 мс, а делает 16 мс, цикл будет повторяться один раз и передаст thisMiniTick как 1. Если дельта была не 16 мс, а 40 мс, цикл будетвыполнить три раза, пройдя 1, 1 и, наконец, 0,5.

Я ошибочно подумал, что в каждом из этих внутренних циклов обновления я мог бы сделать velocity.y += (gravity * thisMiniTickRelative), но это не работает.На более высоких частотах кадров применяется недостаточная гравитация, вызывающая более высокий скачок, а на более медленных кадровых показателях прыжок ниже (хотя и не так близко, как это заметно).

Есть ли способ сделать это, который будет работать практически для всех кадровых скоростейили я должен прибегнуть к установке верхней и нижней границ для delta?

Цикл «внутреннего обновления»:

    float timeRemaining = delta/1000f; 
    while(timeRemaining > 0)
    {
        float thisMiniTick = Math.min(timeRemaining, 1f / FRAMES_PER_SECOND);
        float thisMiniTickRelative = thisMiniTick / (1f / FRAMES_PER_SECOND);

        updateInput(container, game, thisMiniTickRelative);
        if (playerAirState)
        {
            playerVelocity.y += (GRAVITY * thisMiniTickRelative);
        }
        clampPlayerVelocity();
        playerPosition.add(playerVelocity);
        doCollisions();
        timeRemaining -= thisMiniTick;
    }

1 Ответ

2 голосов
/ 19 декабря 2011

Не думайте об этом, как о "использовании верхней и нижней границы для delta".Ваше приложение и потоки зависят от времени планирования ОС для вашего приложения, среди всех других требований к системе, и того, о чем вы просто должны знать.Эта проблема устарела в играх на ПК, как и в тот день, когда мы перешли от однозадачных операционных систем к многозадачным.

С помощью Slick вы можете (и должны) отключать обновления логики от обновлений рендеринга,именно поэтому значение delta передается вокруг вашего приложения.Сделайте это, используя методы .setMinimumLogicUpdateInterval и .setMaximumUpdateInterval .

В проектах, над которыми я работал, включая один в Slick, я обнаружил, что все, что в 30-60 логических обновлениях засекунда (от 30,3 миллисекунд до 16,6 миллисекунд между обновлениями) прекрасно работает и обеспечивает необходимую плавность вычислений движения, физики и столкновений.

В буквальном смысле это означает, что для 30-60 обновлений логики вВо втором диапазоне вы хотите сделать следующее:

container.setMinimumLogicUpdateInterval(16);  // max 60 logic updates per second
container.setMaximumLogicUpdateInterval(31);  // min 30 logic updates per second

Также, попытка вычислить значение timeRemaing является обычной ошибкой, но вы не хотите этого делать.Вы просто хотите умножить, сколько вы двигаетесь, на сколько времени прошло.Если прошло 30 миллисекунд, это примерно 1/33 секунды, поэтому вы должны перемещать игровой объект на 1/33 от величины, которую он будет перемещать за 1 секунду.

float timeElapsed = delta/1000f;

playerVelocity.y += (GRAVITY * timeElapsed);

С верхним / нижнимграницы установлены как указано выше, вы уверены, что timeElapsed всегда будет значением между 0.03 и 0.06.Если ваша игра застряла, а частота кадров замедлена, обновления логики все равно не выйдут за эти пределы.Вместо этого произойдет замедление всей игры (как и должно быть, как в старые времена Sega, когда на экране было слишком много), но вычисления столкновений и физики будут работать, как и ожидалось.

...