Проблемы с 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() в игровом цикле.