Всем привет. В этой краткой статье я расскажу как сделать в вашем приложении на Corona SDK таймер с приемлемым показателем точности отсчета. Так же рассмотрим в чем заключаются проблемы стандартного таймера.
В статье будет решаться следующая задача: Сделать приложение которое будет показывать время прошедшее с момента включения приложения с его обновлением 1 раз в секунду.
Создаем стандартный таймер и выводим его тики.
Вроде бы все очевидно, но в работе этого решения есть особенности:
Для решения проблем прошлого способа используем следующую конструкцию, в этом методе мы применяем таймер с максимально возможной скорость, но сигналом для тика таймер будет расчет опирающийся на источник точного времени системы.
Разбираем особенности этого метода. Несмотря на то что мы указываем частоту тиков 1мс как было описано выше реальные кванты тиков будут выполняться с раз в 16(33)-50мс, а это и будет определять максимально возможную погрешность приведенного выше метода, погрешность будет изменяться в диапазоне 0..50мс от тика к тику, т.е. частота следования тиков будет менее стабильной чем в первом методе, но величина этой погрешности на любой дистанции (даже длиной в годы) будет одинаковой, т.е. даже через год наш очередной тик будет иметь погрешность в этих же пределах относительно самого первого тика.
Приведу пример того как можно проверить справедливость всего выше сказанного. Приведенный исходник будет раз в секунду выводить текущее время прошедшее с момента включения приложения для двух таймеров(отдельно) и показывать накопленную за время работы ошибку.
Всем удачи!
В статье будет решаться следующая задача: Сделать приложение которое будет показывать время прошедшее с момента включения приложения с его обновлением 1 раз в секунду.
1.Очевидное стандартное решение.
Создаем стандартный таймер и выводим его тики.
timeout = 1000
timer.performWithDelay( timeout,function(event)
print(event.count)
end,0)
Вроде бы все очевидно, но в работе этого решения есть особенности:
- Во-первых стандартный таймер способен корректно и достаточно точно отрабатывать таймауты начиная с 300-400мс, а все что ниже этого значения начинает очень существенно отставать, но наш случай другой так как таймаут более указанных пределов. Минимально возможный период тиков таймера (если указать 1 мс) 1/fps, т.е. 16.(6)мс для 60 кадров или 33.(3)мс для 30 кадров.
- Во-вторых даже на указанном относительно точном периоде имеется случайная погрешность около 5-10 мс с каждого тика, т.е. за час набегает погрешность 15-30секунд. Эту проблему частично можно решить отняв 5 мс от того значение которое указывается в параметре при создании таймер, т.е. вместо 1000 указать 995.
- В-третьих если в вашем приложении будут возникать мелкие фризы вызванные результатом работы другого кода или нестабильной работой устройства, эти фризы так же будут добавляться в копилку отставания в работе таймера.
- В четвертых если свернуть приложение на какое-то время и после этого его заново развернуть, все время которое приложение было свернуто будет исключено из количества секунд работы приложения.
2. Хорошее решение.
Для решения проблем прошлого способа используем следующую конструкцию, в этом методе мы применяем таймер с максимально возможной скорость, но сигналом для тика таймер будет расчет опирающийся на источник точного времени системы.
local timeout = 1000--таймаут
socket = require "socket"
local start_time = socket.gettime()*1000--время инициализации таймера(старт приложения)
local good_time = 0
timer.performWithDelay( 1,function(event)
local new_time = socket.gettime()*1000--новая временная метка
local total_time = new_time - start_time--прошло времени с момента запуска приложеня
local num = math.floor(total_time/timeout)--количество прошедших целых периодов размером в timeout
if num > good_time then--если пришло время нового тика
good_time = num--новый тик
print(good_time)
end
end,0)
Разбираем особенности этого метода. Несмотря на то что мы указываем частоту тиков 1мс как было описано выше реальные кванты тиков будут выполняться с раз в 16(33)-50мс, а это и будет определять максимально возможную погрешность приведенного выше метода, погрешность будет изменяться в диапазоне 0..50мс от тика к тику, т.е. частота следования тиков будет менее стабильной чем в первом методе, но величина этой погрешности на любой дистанции (даже длиной в годы) будет одинаковой, т.е. даже через год наш очередной тик будет иметь погрешность в этих же пределах относительно самого первого тика.
3. Проверка результатов
Приведу пример того как можно проверить справедливость всего выше сказанного. Приведенный исходник будет раз в секунду выводить текущее время прошедшее с момента включения приложения для двух таймеров(отдельно) и показывать накопленную за время работы ошибку.
local timeout = 1000
socket = require "socket"
local start_time = socket.gettime()*1000--время инициализации таймера
local good_time = 0--время сокетного счетчика
local bad_time = 0--время обычного счетчика
--плохой таймер
timer.performWithDelay( timeout,function(event)
bad_time = event.count
local bad_delta = (socket.gettime()*1000 - start_time) - (bad_time*timeout)
print('Bad tick: '..bad_time, 'Delta: '..bad_delta)
end,0)
--хороший таймер
timer.performWithDelay( 1,function(event)
local new_time = socket.gettime()*1000
local total_time = new_time - start_time
local num = math.floor(total_time/timeout)
if num > good_time then
good_time = num
local good_delta = (socket.gettime()*1000 - start_time) - (good_time*timeout)
print('Good tick: '..good_time, 'Delta: '..good_delta)
end
end,0)
Всем удачи!