Подтвердить что ты не робот

NSTimer vs CACurrentMediaTime()

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

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

В частности, я не уверен в возможностях класса NSTimer и CACurrentMediaTime(). Трудно проверить эмпирически, потому что я не уверен, что имеет большую ошибку. Например, используя NSTimer с повторяющимся интервалом 0,008 (~ 2updates/screen refresh) и вызывая CACurrentMediaTime() при последовательных вызовах, я нахожу, что временной интервал между вызовами варьируется от 0,0075 до 0,009. Трудно сказать, что несет ответственность за (небольшую) несогласованность. Поэтому для определения временного шага я должен:

  • Предположим, что NSTimer достаточно точен, чтобы использовать временной интервал NSTimer в качестве шага времени игрового цикла.

  • Используйте CACurrentMediaTime(), чтобы определить временной интервал между последовательными вызовами цикла игры.

Студент и новый для всего этого - пожалуйста, будь приятным:) Любые советы очень ценятся. Спасибо за ваше время.

4b9b3361

Ответ 1

NSTimer не является таймером реального времени. Он даже не закрывается, и это не значит быть. Если вы смотрите на что-либо быстрее, чем на полсекунды, NSTimer - неправильный инструмент. Я бы даже не рекомендовал его для вещей в течение секунды. Для многосекундных вещей, и особенно многоминутных вещей, когда вам не очень-то важно, когда он стреляет, это здорово. Я использую его все время.

CACurrentMediaTime() не является таймером. Это обертка вокруг наиболее точной функции времени в системе: mach_absolute_time(). Поэтому, если вы действительно волнуете, в какое время это сейчас, и вы хотите, чтобы это было понятным человеком, CACurrentMediaTime() - это ваша функция. mach_absolute_time() даст вам действительно точное число, но оно основано на абсолютном блоке абсолютного времени Маха, который на самом деле не указывает на то, что надоедливые люди думают (и каждый процессор имеет разный масштаб). Вот почему мы CACurrentMediaTime() облегчили нашу жизнь.

ОК, поэтому NSTimer не используется в режиме реального времени, а CACurrentMediaTime() не является таймером. Что программист игры?

Grand Central Dispatch включает в себя одну из лучших систем "сделай эту работу примерно в это время" у нас. Это источник отправки. Я говорю "об этом времени", потому что GCD по-прежнему не является "реальным временем" в том смысле, что ребята из RTOS это понимают. Но в реальном времени достаточно для разработчиков игр. Найдите "Создание таймера" в Concurrency Руководстве по программированию. Также взгляните на dispatch_after(), что хорошо для однократного запуска "запустите это после задержки".

Помните, что все, что работает в вашем основном потоке (поток пользовательского интерфейса, где выполняется весь чертеж), собирается делиться временем со всем остальным в этом потоке. Так часто вам придется делать вычисления в фоновом потоке, пока вы обрабатываете рисование и взаимодействие с пользователем в основном потоке. Это та вещь, с которой GCD dispatch_queues разработаны, чтобы помочь вам. С другой стороны, помните, что многие устройства iOS являются одноядерными. Таким образом, "фоновый поток" является немного неправильным. За один раз на CPU может работать только одна вещь. Вот почему перемещение вещей на GPU настолько важно (см. Ниже).

Вы также можете серьезно посмотреть на такие системы, как cocos2d, что является очень хорошим игровым движком. Он заботится обо всех этих деталях для вас и позволяет сосредоточиться на игровой части.

Оставаясь в рамках Apple, вы также должны взглянуть на Core Animation. Если вы перемещаете вещи на экране с помощью таймеров, вы не должны этого делать. Core Animation - это то, как вы перемещаете вещи на экране. Он заботится о многих деталях для вас, быстрее и потребляет гораздо меньше энергии, чем вы делали самостоятельно, и это приносит большую часть работы на GPU (как я упоминал выше). Это немного больше предназначено для элементов пользовательского интерфейса, чем игр, но его можно определенно использовать для создания простых игр.

И, конечно, там GLKit, но это совсем другая вещь....

Ответ 2

В соответствии с документацией NSTimer the effective resolution of the time interval for a timer is limited to on the order of 50-100 milliseconds., что, вероятно, связано с тем, что вы видите изменение в интервале времени.

Что я предлагаю сделать, это изменить интервал обновления до 0,016 с, так как нет никаких причин, по которым ваше состояние игры будет обновляться чаще, чем экран может нарисовать его. Затем вы можете использовать CADisplayLink для обработки времени. Это должно быть очень точным, поскольку он использует частоту обновления дисплеев.