Игры для iOS и управление Run-Loop - PullRequest
28 голосов
/ 27 января 2011

Во-первых, мой вопрос: как вы управляете вашей iOS Run-Loop?

Следующая моя причина: я исследовал это с различными прототипами (против ранней стадии разработки) и обнаружил ряд недоумений.

  • Во-первых, проблемы ввода и цикл выполнения побуждают меня попробовать следующее:
    • при использовании наиболее рекомендуемой системы (CADisplayLink) я заметил, что некоторые сенсорные входы сбрасываются, когда загрузка процессора заставляет переворот буфера (presentRenderBuffer) ждать кадра. Это происходит только на устройстве, а не в симуляторе (досадно - похоже, это связано с ожиданием блокировки vsync в главном потоке и с тем, как процесс запуска цикла приложения касается ввода и приема сообщений)
    • при использовании следующей наиболее рекомендуемой системы (NSTimer) я заметил, что некоторые сенсорные входы сбрасываются, когда нагрузка на процессор достигает определенной точки в симуляторе, но не в устройстве (также раздражает). NSTimer также значительно снижает точность при запуске моих обновлений
    • при использовании наименее рекомендуемой системы (запуск цикла выполнения в собственном потоке, управляемом изнутри с помощью высокоточного таймера, созданного из mach_absolute_time, все мои проблемы с сенсорным вводом исчезают, однако мой код ASSERT теперь перехватывает неверный поток и только если я засыпаю после программного прерывания. (Мой код подтверждения похож на http://iphone.m20.nl/wp/?p=1). Мне действительно нравится, когда мой код подтверждения прерывается сразу на той линии, которая вызвала проблему, поэтому это решение на самом деле не работает для меня: труднее отладки.
  • Во-вторых, потерянное время:
    • при изучении системы я обнаружил, что независимо от частоты кадров (причудливо, но я полагаю, что статистически это все еще имеет смысл w / vsync), я жду приблизительно 22% времени на vsync. Я подтвердил это, перемещаясь по glFlush / glFinish и играя с тем, как часто я делаю вызовы presentRenderBuffer. Это ключевой момент, когда я хотел бы обрабатывать ИИ и т. Д., А не просто останавливать блокирующий вызов gl. Единственный способ обдумать это - перенести рендеринг в собственный поток, но я не уверен, стоит ли начинать ре-архитектуру многопоточности на однопроцессорном устройстве.

Так кто-нибудь нашел волшебную пулю вокруг этих проблем? У кого-нибудь есть убийственная архитектура цикла выполнения, которая обалденная на этой платформе? На данный момент мне кажется, что я должен выбрать меньшее из зол.

1 Ответ

6 голосов
/ 04 февраля 2011

Для своих собственных проектов iOS я использую классический подход (создайте окно .nib, создайте класс, наследующий EAGLView, добавьте EAGLView к представлению в контроллере представления, который помещен в его собственный .nib).

На работе я использовал немного другой подход, основанный на SDL, который вы можете просмотреть в нашей библиотеке с открытым исходным кодом, АПРЕЛЬ .Главная цель APRIL - поддержка как можно большего количества платформ, сохраняя при этом простоту (только управление окнами и вводом), а также ясность в вопросах лицензирования и бесплатное использование.Наши разработчики хотят писать приложения на одной платформе (Windows, Mac или Linux, в зависимости от вкусов и желаний), а затем код передается мне для адаптации к другим платформам.

В подходе, который мы используем в APRIL, вы не создаете никаких .nibs, а при вызове UIApplicationMain вы указываете класс делегата в качестве его четвертого аргумента.Основной код игры остается абсолютно одинаковым для каждой платформы, и только специфичные для платформы вещи находятся в коде #ifdef или абстрагированы в вспомогательной библиотеке.

В делегате приложения вы создаете контроллер представленияи окно:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    // create a window.
    // early creation so Default.png can be displayed while we're waiting for 
    // game initialization
    window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // viewcontroller will automatically add imageview
    viewController = [[AprilViewController alloc] initWithWindow:window];
    [viewController loadView];

    // set window color
    [window setBackgroundColor:[UIColor blackColor]];

    // display the window
    [window makeKeyAndVisible];

    // thanks to Kyle Poole for this trick
    // also used in latest SDL
    // quote:
    // KP: using a selector gets around the "failed to launch application in time" if the startup code takes too long
    // This is easy to see if running with Valgrind

    [self performSelector:@selector(runMain:) withObject:nil afterDelay:0.2f];
}

Обратите внимание, как мы задерживаем запуск на 0,2?Вот почему я упоминаю вид изображения выше.В течение этих 0,2 секунд у нас сразу после Default.png будет отображаться пустой экран, и перед переносом элемента управления в runMain: вводится дополнительная задержка, которая освобождает элемент управления от основного приложения:

- (void)runMain:(id)sender
{       
    // thanks to Kyle Poole for this trick
    char *argv[] = {"april_ios"};
    int status = april_RealMain (1, argv); //gArgc, gArgv);
#pragma unused(status)
}

Итак,Теперь элемент управления никогда не возвращается обратно в реальный основной цикл UIApplication.Затем вы создаете свой собственный главный цикл.

    void iOSWindow::enterMainLoop()
    {
            while (mRunning) 
            {
                    // parse UIKit events
                    doEvents();
                    handleDisplayAndUpdate();
            }
    }

    void iOSWindow::doEvents()
    {
            SInt32 result;
            do {
                    result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
            } while(result == kCFRunLoopRunHandledSource);
    }

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

Оба изэти подходы используют CADisplayLink, если они поддерживаются ОС.Я не заметил никаких проблем ни с одним из методов, хотя мои частные проекты в основном основаны на акселерометре.Я подозреваю, что подход АПРЕЛЯ может также устранить некоторые проблемы.

...