Предыстория
Будучи в процессе разработки своей первой html5 игры я столкнулся с рядом трудностей, для большинства из них полно готовых решений в сети, однако грамотного ответа на вопрос:«Как сделать паузу в html5 игре?» — Я не нашел. Всех кому данная тема интересна или необходима — прошу далее…
Подробнее о решениях
Все решения найденные мной в интернете так или иначе действуют по принципу while.
Примеры ниже:
Пример 1
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function demo() {
console.log('Taking a break...');
await sleep(2000);
console.log('Two second later');
}
demo();
В данном случае мы задаем паузу на какое-то время, по его прошествии игра продолжается…
Данное решение не подойдет в большинстве случаев хотя бы потому, что мы не знаем на сколько пользователь поставит паузу, а также во время выполнения функции пользователь не сможет взаимодействовать с меню.
Пример 2
function render(){
if(canRender == false){
requestAnimationFrame(render);
}else{
//some code
requestAnimationFrame(render);
}
Постоянный перезапуск и отслеживания действий пользователя, память тратится в пустую.
Мое решение
Итак, выделив основные проблемы найденных на просторах интернета решений, я, собрав все вместе, получил следующее:
Во-первых, объявим сам объект редеринга, глобальную переменную положения объекта и переменную для паузы, а также массив, для чего он узнаем чуть позже.
let sqrt=document.getElementById('sqrt'),rend=0,pause=false,functions=[];
Теперь объявим саму функцию рендеринга, которую и нужно ставить на паузу:
function render(){
rend+=1.5;
sqrt.style = 'bottom:' + rend +'vh';
if(rend<80){
requestAnimationFrame(render);
}else{
rend=0;
return;
}
}
Далее интегрируем код для паузы в функцию(в моем примере она одна, в Вашем случае функций может быть больше)
function render(){
if(pause!=false){
//Добавляем имя функции в массив для дальнейшего запуска
functions.push("render()");
//прекращаем выполнение функции
return;
}
rend+=1.5;
sqrt.style = 'bottom:' + rend +'vh';
if(rend<80){
requestAnimationFrame(render);
}else{
rend=0;
return;
}
}
Итак, дело за малым, добавляем функцию для обработки pause/unpause
function SetPause(){
if(pause==true){
UnPause();
}else{
pause=true;
}
}
function UnPause(){
pause=false;
//проходим по всем приостановленным функциям и запускаем их снова
for(i=0;i<functions.length;i++){
eval(functions[i]);
}
//обнуляем массив для дальнейшего использования
functions =[];
}
Все готово, мы получили механизм не кушающий память за зря и дающий возможность взаимодействия со страницей во время паузы.
Данная статья была написана в целях помощи. Если кто либо видел такое решение ранее — прошу прощения. Спасибо за внимание!
Комментарии (5)
kireevmp
25.04.2019 17:19В целом, если переносить методологию работы игр из нативных приложений (C++/C# и так далее) на js, то именно «ресуроемкий» (Пример 2) используется повсеместно, ведь именно там находится считывание кнопок управления.
В случае игр на js следовало бы создать какой-то стейт, который в game loop рендерился бы, а пауза просто меняла логику внутри game loop так, чтобы реакции на кнопки управления не обрабатывались, рисовалось окно паузы и так далее. Хотелось бы всё равно иметь архитектуру.
А про оформление кода тут уже сказали, не буду повторяться.SbWereWolf
26.04.2019 02:52Вполне возможно что автор просто неправильно оформил статью, в смысле блоки с кодом.
Что автор хотел рассказать, до меня не доехало. Коменты понятней статьи :)
helg1978
26.04.2019 15:42Автор, установите beautify plugin.
По теме — да, как написали выше, стейт «пауза» поможет в game loop, рендер вообще не надо трогать, на состояние должен смотреть апдейтер, или аналогичная сущность управляющая логикой игры.
Sirion
Это очень сильно зависит от архитектуры игры. При классической архитектуре с game loop мы просто добавляем туда флаг, при наличии которого большинство игровых механик перестают обрабатываться в теле основного цикла. У вас, судя по всему, архитектура отсутствует в принципе. Также у вас ужасный стиль кода и не менее ужасное его форматирование. Не хочу показаться грубым, но, возможно, вам пока не стоило бы пытаться чему-то научить других?
Я бы рекомендовал вам почитать, например, вот это, если владеете аглицкой мовой. Ну или просто почитать что-нибудь)
qnok
Отвечу за автора огромным спасибо за наводку на книгу. Как раз то, что я искал/хотел почитать после паттернов от четы Фрименов.