Проблемы с Android Gameloop (openGL ES 2.0)

обзор

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

Я подтвердил, что заикание происходит, когда кадры пропускаются.

  • Когда есть пропуски кадров, как я могу остановить анимацию, которая становится прерывистой?

Если абсолютно необходимо пропустить кадры (я допускаю, что на некоторых устройствах будут случаи, когда это произойдет), как я могу смягчить прерывистость?

  • onDrawFrame (GL10 gl), кажется, вызывается до 24 мс с момента последнего вызова.

На моем планшете Google Nexus 10 мой фактический рендеринг может занять от 5 до 14 мс, а мои обновления игры - от 0 до 4 мс, поэтому большую часть времени он должен хорошо вписываться в интервал времени 16.6666. Однако, когда я удаляю все из onDrawFrame, он, кажется, вызывается где-то между 16 и 25 мс. (В большинстве случаев оно превышает 16 мс), поэтому оно пропускает много кадров - даже без рендеринга или вызова обновлений!!

Похоже, это идет вразрез с тем, что устройство работает на скорости 60FPS - это делает VSync? Какой смысл отнимать больше 16 мс?

Вещи, которые я пытался

ОК, я попытался создать отдельный поток, в котором я запускаю свои обновления (опять же, ограничив их до 60 в секунду). Я все еще понимаю проблему.

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

Я действительно борюсь с этим, поэтому я надеюсь, что кто-то может помочь!

Код

float interpolation;
long nextGameTick = System.currentTimeMillis();
//loop counter
int loops;
//This is the amount of frames that we allow our app to skip before logic updating is affected (generally shouldn't happen)
final int maxFrameskip = 5;                             
//Game updates per second
final int ticksPerSecond = 60;
//Amount of time each update should take        
final int skipTicks = (1000 / ticksPerSecond);

    public void onDrawFrame(GL10 gl) {


        //Set/Re-set loop back to 0 to start counting again
        loops=0;

        while(System.currentTimeMillis() > nextGameTick && loops < maxFrameskip){

        SceneManager.getInstance().getCurrentScene().updateLogic();
        nextGameTick+=skipTicks;
        timeCorrection += (1000d/ticksPerSecond) % 1;
        nextGameTick+=timeCorrection;
        timeCorrection %=1;
        loops++;
        tics++;

     }

        interpolation = (float)(System.currentTimeMillis() + skipTicks - nextGameTick)
              / (float)skipTicks; 

    render(interpolation);
}

Применение интерполяции

render(float interpolation){

    //This example shows interpolation for X axis only.  Y position (spriteScreenY is assumed to be valid)
    interpolatedPosX = spriteGridX+(SpriteXVelocity*dt)*interpolation;
    spriteScreenPosX = interpolationPosX * screenWidth;

    drawSprite(spriteScreenX, spriteScreenY);           


}

1 ответ

Попробуйте использовать RENDERMODE_WHEN_DIRTY. Это означает, что больше не используется onDrawFrame, а вместо этого используется requestRender() в игровом цикле.

Другие вопросы по тегам