Как получить постоянную скорость на новых и старых iPhone? - PullRequest
4 голосов
/ 10 июля 2010

Я в процессе создания 2D-игры в OpenGL ES для iPhone.Я вызываю свой игровой цикл с использованием NSTimer с интервалом 0,002 (60 кадров в секунду) с повторениями, установленными на «НЕТ» (я снова запускаю NSTimer изнутри функции в соответствии с рекомендациями):


-(void)gameLoop:(id)sender {
    double currTime=(double)CACurrentMediaTime();
    m_FPS_framesThisSecond++;
    float timeThisSecond=currTime-m_FPS_lastSecondStart;
    if (timeThisSecond>1.0f) {
        m_FPS=m_FPS_framesThisSecond;
        m_FPS_framesThisSecond=0;
        m_FPS_lastSecondStart=currTime;
    }

    [game update];
    [game render];

        //Continue the loop
    [NSTimer scheduledTimerWithTimeInterval:0.002 target:self selector:@selector(gameLoop:) userInfo:nil repeats:NO];
}

Это работает гладко на моем 3GS, однако, когда я тестирую это на 2G, игра работает намного медленнее, и иногда я получаю случайные пустые кадры.Когда я опускаю интервал до 0,033 (30 кадров в секунду).Это слишком медленно в 3G.

Я знаю, что должен быть какой-то способ получить согласованное воспроизведение на обоих устройствах.Doodle Jump работает на обоих телефонах одинаково плавно и с одинаковой частотой кадров.

Ответы [ 2 ]

2 голосов
/ 10 июля 2010

Фактически существует два типа частоты кадров:

  • Частота кадров дисплея: частота, с которой экран перерисовывается
  • Логическая частота кадров: скорость обновления игровой логики (скорость игры)

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

Проверьте алгоритм «Постоянная скорость игры с максимальным FPS», описанный в deWiTTERS Game Loop Появится игровая логикаработать с одинаковой скоростью как на 3G, так и на 2GS, но частота кадров дисплея будет соответствовать более медленному процессору 2G.Хотя это и не рассматривается в статье выше, вы также можете ограничить частоту кадров дисплея для экономии заряда батареи.

2 голосов
/ 10 июля 2010

Существенная проблема заключается в следующем:

ваша игра должна обновляться в зависимости от времени, прошедшего с момента последнего рендеринга, а не от того, сколько раз она рендерилась.Предположим, вы вычисляете положение спрайта на основе некоторой скорости.Новая позиция должна рассчитываться на основе времени между рендерами, а не с предположением, что с момента последнего рендеринга прошло 0,002 секунды.Это называется FPS-независимой анимацией.

Итак, вот простой пример:

// FPS dependent animation
int x = sprite.x + sprite.velocity.x

Правильный способ сделать это - использовать время с момента последнего рендеринга и обновлять его пропорционально.В следующем коде предполагается, что 0,002 является временной базой.

// FPS independent animation
int x = sprite.x + sprite.velocity.x * time_since_last_render/0.002

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

Побочная проблема, вы не всегда должны рендерить следующий кадр на 0,002 секунды в будущем.Вы должны увидеть, сколько времени потребовалось для рендеринга текущего кадра, вычтите это из 0,002 и используйте это для планирования следующего рендера.Естественно, это число будет иметь минимальное значение ноль, поэтому на медленных устройствах вы не начнете планировать в прошлое.Например, если вашей функции рендеринга требуется ровно 0,002 секунды, это излишне снизит частоту кадров вдвое.

...