Corona SDK точный таймер

от автора

Всем привет. В этой краткой статье я расскажу как сделать в вашем приложении на Corona SDK таймер с приемлемым показателем точности отсчета. Так же рассмотрим в чем заключаются проблемы стандартного таймера.
В статье будет решаться следующая задача: Сделать приложение которое будет показывать время прошедшее с момента включения приложения с его обновлением 1 раз в секунду.

1.Очевидное стандартное решение.

Создаем стандартный таймер и выводим его тики.

timeout = 1000 timer.performWithDelay( timeout,function(event) 	print(event.count) end,0)

Вроде бы все очевидно, но в работе этого решения есть особенности:

  • Во-первых стандартный таймер способен корректно и достаточно точно отрабатывать таймауты начиная с 300-400мс, а все что ниже этого значения начинает очень существенно отставать, но наш случай другой так как таймаут более указанных пределов. Минимально возможный период тиков таймера (если указать 1 мс) будет составлять 10-50мс причем с большим разбросом от тика к тику.
  • Во-вторых даже на указанном относительно точном периоде имеется случайная погрешность около 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мс как было описано выше реальные кванты тиков будут выполняться с раз в 10-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)

Всем удачи!


ссылка на оригинал статьи https://habr.com/post/422443/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *