Что является лучшим способом создания игрового цикла на iPhone, кроме использования NSTimer?

Я программирую игру на iPhone. В настоящее время я использую NSTimer для запуска моего обновления/рендеринга. Проблема в том, что (после профилирования) я, кажется, теряю много времени между обновлениями/рендерами, и это, похоже, в основном связано с временным интервалом, который я подключаю к NSTimer.

Итак, мой вопрос - это лучшая альтернатива использованию NSTimer?

Один вариант для каждого ответа.

Ответ 1

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

- (void) gameLoop
{
    while (running)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        [self renderFrame];
        [pool release];
    }
}

- (void) startLoop
{
    running = YES;
#ifdef THREADED_ANIMATION
    [NSThread detachNewThreadSelector:@selector(gameLoop)
    toTarget:self withObject:nil];
#else
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0f/60
    target:self selector:@selector(renderFrame) userInfo:nil repeats:YES];
#endif
}

- (void) stopLoop
{
    [timer invalidate];
    running = NO;
}

В методе renderFrame Вы готовите фреймбуфер, рисуете рамку и представляете фреймбуфер на экране. (P.S. Существует большая статья о различных типах игровых петель и их плюсах и минусах.)

Ответ 2

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

  • Определите интервал обновления, которым вы были бы довольны, и это больше, чем один проход через основной цикл.
  • В начале цикла возьмите текущую временную метку любого разрешения, которое у вас есть, и сохраните его.
  • В конце цикла возьмите еще одну временную метку и определите прошедшее время с момента последней отметки времени (инициализируйте это до цикла).
  • sleep/delay для разницы между вашим идеальным временем кадра и уже прошедшим временем для этого кадра.
  • В следующем кадре вы можете даже попытаться компенсировать неточности в интервале ожидания, сравнивая с меткой времени в начале предыдущего цикла. Сохраните разницу и добавьте/вычтите ее из интервала ожидания в конце этого цикла (сон/задержка может зайти слишком долго или слишком коротко).

Возможно, вы захотите иметь механизм предупреждения, который позволяет вам знать, слишком ли вы настроены время (i, e, если ваше время сна после того, как компенсация меньше 0, что означает, что вы занимаете больше времени для обработки, чем позволяет частота кадров). Эффект будет в том, что ваша игра замедляется. Для дополнительных точек вам может понадобиться упростить рендеринг на некоторое время, если вы обнаружите это, до тех пор, пока вы снова не получите достаточную запасную емкость.

Ответ 3

Используйте CADisplayLink, вы можете найти, как в проекте шаблона OpenGL ES, представленном в XCODE (создать проект, начинающийся с этого шаблона, и посмотреть на класс EAGLView, этот пример основан на открытом GL, но вы можете использовать CADisplayLink только для других видов игр