Комментарии 21
есть же requestAnimationFrame?
Да, так тоже можно делать, но зачастую у объектов довольно много аспектов поведения, и проверять их все в каждом тике получается накладно по производительности.
То есть, допустим, общие аспекты, вроде гравитации, стоит применять в Object.tick()
, а поведение, повторяющееся через какой-то промежуток времени, вроде атаки вражеского юнита в платформерах, удобно вынести в отдельный метод и управлять им через отдельный таймер.
Ужасно запутаетесь на асинхроне. Вспоминая схемотехнику, все действия там проходят по фронту задающего сигнала не просто так. Если у вас половина процессора будет работать по одному тактовому сигналу, а вторая — по другому — очень быстро начнется жуткий рассинхрон и потеря данных.
Ну и да, в отличие от requestAnimationFrame с подсчетом прошедшего времени руками, setTimeout крайне не стабильный по времени. Если так хочется — можно сделать подобную библиотеку в виде обертки над самим requestAnimationFrame.
Ну и да, все игровые движки, и книги, и вообще мануалы по созданию игр крутятся поверх так называемой game loop, в котором даже если и параллельно, однако обрабатывается все синхронно
В схемотехнике по фронту происходят не действия — а фиксация изменений в триггерах.
Хотелось бы увидеть пример "жуткого рассинхрона и потери данных" в js.
Даже если будут потери в 5-10 мс, это не критично для поведения, описанного выше. Естественно, все движения юнитов и коллизии должны считаться в game loop. Что касается путаницы, то можете глянуть код моего проекта из предыдущего поста. Мне кажется, там всё достаточно ясно.
Переключение гл. меню/настройки/игра/уровни легко реализовать самописным сценменеджером, в нем же хранить ссылку на текущую сцену, лучше на две сцены, текущую и предыдущую используемую (возможна ситуация, что они обе должны обновляться, например скролинг он уровня к меню, когда мы видим сперва кусочек уровня и меню, а только потом меню целиком). И тогда вместо
gameTimers.pauseAll();
menuTimers.resumeAll();
будет что-то типа
sceneManager.SetScene(menu);
где
SetScene =
function(scene) {
this.OldScene = this.CurrentScene;
this.CurrentScene = scene;
}
А в таймере вызывать обновление sceneManager, который обновит нужные сцены.
Да, я тоже за один общий таймер. А скорость объектов не дискретная.
Почему вам не нравятся обещания (Promises)? С ними же удобнее делать сложные последовательности анимаций.
Заметил у вас еще одну проблему: ваша функция setTimeout
не является совместимой со стандартной.
То есть если захочется добавить возможность "заморозки" в существующий код — не получится просто пройтись по коду и заменить все setTimeout
на какие-нибудь ts.setTimeout
Из отличий — ваша функция не умеет принимать параметры для функции обратного вызова и не умеет выполнять строку.
Вы про эти — setTimeout(calback, delay, [arg1], [arg2], [arg3])
— аргументы?
Я бы для анимации использовал что-то вроде PixiJS.
Управляем кучей таймеров в JavaScript