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

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

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

Пожалуйста, по одной альтернативе на каждый ответ.

Комментарии к вопросу (2)

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

- (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. Есть отличная статья о различных типах игровых циклов и их плюсах и минусах).

Комментарии (4)

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

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

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

Комментарии (0)

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

Комментарии (0)