Управление на куп таймери в JavaScript
Последната публикация беше за това как написах игра за състезанието js13kGames, чиято цел е да вместя моя занаят в 13 килобайтов стек от отворени уеб технологии.
В допълнение към триковете за минимизиране, играта ме вдъхнови да създам инструмент за управление на голям брой таймери, като ги обвия в удобен интерфейс и ги групирам. Кодът и случаите, в които може да ви бъде полезен, са под разфасовката.

Демо, където можете да изстрелвате ракети и разгледайте няколко примера за код
Къде може да се използва?
Често логиката в игрите е разделена на състояния (състояния) - малки независими части, например: меню, ниво, екран за победа. Ако приемем, че играчът може да отиде в менюто по време на играта, спирайки случващото се в нивото, трябва да се погрижим за запазването на контекста на таймерите.
В моя сравнително беден опит се натъкнах на следното решение на този проблем. Във всеки обект с логика, свързана с времето, се създават собствени таймери и когато обектът бъде унищожен, те се изчистват. Недостатъкът на това решение е, че всички таймери трябва да се изчистят ръчно.
Още един пример. Ако пространството на играта се състои от много малки локации (помислете за The Binding of Isaac, например), може да искаме да съхраняваме състоянията на обекти и единици в някои от тях. Отново трябва да напишете възможност за пауза на таймери за всяка единица.
Основната идея е да се създаде "пространство от таймери", което може да бъде напълно поставено на пауза, възобновено, изчистено и повторно използвано. Първата, примитивна версия се появи още по време на разработката на играта, а през изминалия уикенд написах по-адекватна версия - timestore.
Два класа се използват като таймери: Изчакване и Интервал. Вътрешно и двете използваниsetTimeout() . И двата класа имат методи с подсказващи имена: .clear(), .pause(), .resume() и някои други. Таймерите могат да се използват директно, но основната функция е в класа Timestore.
Когато създаваме таймер чрез timestore, той се съхранява в колекция и след това може да бъде достъпен не само директно, но и чрез ID:
Важно : Не можете да използвате числа (и низове като '10' ) като потребителски идентификатори, тъй като числата се използват като идентификатори по подразбиране в хранилището за време.
Управление на цели колекции:
Ако предадете флага fireBeforeClear на таймера, тогава по време на изчистването той ще работи:
Друг полезен метод е .getTimeLeft(). Връща броя милисекунди до задействането на следващия таймер.
Какво следва?
Планове за следващите два-три дни:
- добавете проверка за потребителски идентификатори, така че номерът да не може да бъде предаден;
- напишете методи като .clearIntervals(['id1', 'id3', 'id5']), за да улесните управлението на части от колекцията;
- добавете Interval.fireCounter - свойство, показващо колко пъти е задействал таймера;
- и свързан метод, Interval.clearIn(times) , който ви позволява да изчистите таймера след няколко задействания.
Също така ще публикувам няколко примера в JSFiddle и CodePen в близко бъдеще. В момента има страница с примери.
PS. Между другото, когато правех timestore, използвах тестове за първи път и за тези, които все още се съмняват, ще кажа: тестовете са готини!
PPS. Преди да започна да пиша код, се опитах да намеря аналози, но не попаднах на нищо подобно. Може би просто търсих лошо, но те са? Моля, споделете, ако сте попаднали на нещо подобно.
PPPS. Можете да прочетете повече за щатите тук.
И тук можете да получите грант за тестов период на Yandex.Cloud. Необходимо е само да въведете "Habr" в полето "секретна парола".