Как работают таймеры в играх?

Знающие люди, подскажите, как работают таймеры в таких играх, как например "Фермер". Где есть N кол-во объектов: деревья, цветы, животные и т.д. и у каждого из них есть собственный таймер отсчета.

Посылать каждую секунду запрос на сервер, чтобы проверить закончились ли таймеры, наверно неправильно. Остается только вариант с постоянной поддержкой соединения. Или есть еще какие методы и технологии?
  • Вопрос задан
  • 6357 просмотров
Пригласить эксперта
Ответы на вопрос 7
RusPOPsy
@RusPOPsy
Говорила мама, учи математику ...
Например таймер до конца
допустим до конца чего либо осталось 180 секунд
Демка

(function($){
    // Количество секунд в каждом временном отрезке
    var days	= 24*60*60,
    hours	= 60*60,
    minutes	= 60;
    
    $.fn.timer = function(callback){
        callback = callback ? callback : function(){}
        return new $.ctimer(this, callback);
    }
    $.ctimer = function(element, callback) {
        callback = callback || function(){}
        var secs = parseInt(element.html());
        function tick(){
            // Осталось дней
            var sec = secs;
            var d = Math.floor(sec / days);
            sec -= d*days;
			
            // Осталось часов
            var h = Math.floor(sec / hours);
            sec -= h*hours;
			
            // Осталось минут
            var m = Math.floor(sec / minutes);
            sec -= m*minutes;
			
            // Осталось секунд
            var s = sec;
            h = (h+"").length<2 ? "0"+h : h;
            m = (m+"").length<2 ? "0"+m : m;
            s = (s+"").length<2 ? "0"+s : s;
            if(secs==0){
                element.html(null);
                callback();
                return false;
            }
            secs--;
            element.html(d+" дн. "+h+":"+m+":"+s);
            setTimeout(tick, 1000);
        }
        tick();
    }
})(jQuery);
Ответ написан
index0h
@index0h
PHP, Golang. https://github.com/index0h
Вы пытаетесь понять как строится дом по цвету маек рабочих))

Обычно есть некое "состояние мира игры". При подключении клиента - организцуется постоянное соединение (udp обычно), далее клиент скачивает текущее состояние мира. Потом в процессе игры сервер и клиент обмениваются сообщениями, (вполне норм, если в асинхронном режиме) клиент запрашивает действие, сервер - либо отвечает об успешности/не успешности, либо отдает "состояние мира", либо diff "состояния мира".
Ответ написан
Скажем в игре Farmerama, с которой я кхм... разбирался ;-) устроено так - с каждым объектом связано поле в котором хранится время следующего события, unix timestamp. Например время когда что-то на поле созреет и тд.
Анимации всякие и визуальное отображение объекта оперирует значением этого поля, то есть если судя по таймеру поле должно уже созреть - на клиенте оно рисуется как готовое. Регулярно клиент посылает на сервер PUSH сообщения в ответ на которые сервер сообщает новое реальное состояние поля, новые значения таймеров в том числе. Так что если возникает какая-то рассинхронизация или задержка в ответе сервера - полое хоть и рисуется как созревшее или убранное или еще какое изменение состояния - но реально состояние игры (добавление или уменьшение ресурсов) произойдет только когда это подтвердит сервер.
Синхронизация с сервером происходит время от времени если даже игрок ничего не делает, и после отправки действий игрока на сервер.
Ответ написан
haiku
@haiku
Думаю, есть еще вариант одновременно крутить таймеры и на сервере и на клиенте, по истечении таймера на клиенте кидать на сервер запрос синхронизационный (Или делать push с сервера на клиента по таймеру). Ес-сно может крутиться и поверх WebSocket с постоянным коннекшеном.
Ответ написан
thecoder
@thecoder
Разработчик веб-приложений и сервисов.
Если речь идет об игре, то все состояния, таймеры, основной цикл реализуются на сервере, а клиент получает обновления, чтобы показать адекватную картинку. Мне кажется важно иметь возможность обновить клиента именно в тот момент, когда произошло событие. Например, пришло сообщение в чате.

Полагаю, подразумевался вопрос "как обновлять состояние игры в браузере". По ссылке расписаны варианты как дергать сервер, с примерами реализации: stackoverflow.com/questions/11077857/what-are-long...

Вариант "дергать каждую секунду" не рассматриваем. Самый простой в реализации на клиенте для старых браузеров: long polling. Но если поддерживаются WebSockets (а сокеты сейчас все, кроме оперы мини поддерживают), надо использовать сокеты. Если забить на IE, то можно Server-sent events.
caniuse.com/#search=web%20sockets
caniuse.com/#search=eventsource
Ответ написан
Комментировать
@maglink
Можно в самом начале, для каждого объекта, передать клиенту информацию о времени начала отсчета и продолжительности отсчета. Например:
objectList = {
object1: {
    timestart: 1420455312000, 
    timeExpire: 180*60*1000, //180 секунд
},
object2: {
    timestart: 1420455300000, 
    timeExpire: 150*60*1000, //150 секунд
},
}
Ответ написан
ruFelix
@ruFelix
Предсказание будущего по руке, таро, кофе.
Вариантов много, в зависимости от качества соединения, приемлемости лагов и возможностей мошенничества.
Но нужно понимать что анимацию в таких играх на сервер не завязывают, игровой сервер отвечает за корректность изменения состояний игрового мира и может выдать текущее состояние игровых объектов.

В общем случае суть где то такая:
1) на сервер отсылается запрос "посадить_укроп_в_грядке_с_координатами(5,5)"
2) Сервер, запоминает состояние грядки в координате 5,5 и присылает ответ, что всё ок, расти будет 300 секунд.
3) Клиент запускает таймер на 300 секунд, по которому будет меняться анимация того как растёт укроп
4) По истечению 300 секунд клиент переводит укроп в координатах 5,5 в состояние "готов к уборке"
5) Пользователь жмёт собрать укроп, на сервер уходит "собирать_урожай_в_координатах(5,5)"
6) Сервер проверяет, что прошло достаточно времени (т.е. 300 секунд +/- лаги) и даёт ответ, что да можно собирать укроп. И сохраняет состояние грядки как пустая, а укроп перекидывает в амбар.

Так же стоит отметить, что секунда на сервере, ещё кое как, близка астрономической, но вот 1 секунда на JS в браузере может быть какой угодно.
Поэтому никто секунды не считает, считают дельту по времени.
Т.е. создают объект на который в котором запоминаются таймауты в секундах, текущее время и функции которые будут вызваны по их истечению. Потом setinterval/setTimeout допустим раз в 1 сотою секунды проверяет дельты текущего времени к сохранённым в этом объекте, и если дельта больше чем таймаут то дёргает функции обработчики.

Для начального варианта сетевого протокола достаточно просто отсылать HTTP запросы по событиям, по мере роста проекта будет понятно в какую сторону оптимизировать протокол т.к. вариаций тут реально много.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы