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

15 ИЮНЯ 2022

------------------------------------------------------------------------

Наш телеграм-канал: t.me/@mailsgun_online

Youtube: youtube.com/@mailsgun_online

------------------------------------------------------------------------

Всем привет. В этой краткой статье я расскажу как сделать в вашем приложении на 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)

Всем удачи!

Метки:
Похожие публикации

Парадоксальный тест, который поможет определиться, на чьей вы стороне — облачных серверов или боевых орков

WAAAGH!!!

Source: habr1

Ну и напоследок напоминаю вам о нашем новом проекте vkserfing bot.