Я пишу игру, которая имеет много временных аспектов. Я использую время, чтобы помочь оценить позиции игрока, когда сетевые сбои и пакеты не проходят (и время между получением пакета и нет). Это игра типа pacman в том смысле, что игрок выбирает направление и не может остановиться, поэтому система имеет смысл (или, по крайней мере, я так думаю).
Итак, у меня два вопроса: 1) Как синхронизировать часы игр при старте, поскольку в сети есть задержка. 2) Можно ли НЕ синхронизировать их и просто предположить, что они одинаковы (мой код не зависит от часового пояса). Это не суперконкурентная игра, где люди меняют свои часы, чтобы обмануть, но все же.
Игра программируется на Java и Python (параллельная разработка как проект)
Ответы:
Я думаю, что это определенно не нормально синхронизировать часы в системе . Пользователь не ожидает, что вы коснетесь системных настроек, и многие системы даже не позволят вам это сделать.
Все, что вам нужно, это иметь корреляцию для преобразования метки времени из часов одной стороны в часы другой стороны. С другой стороны, вам нужно, чтобы это соотношение было достаточно точным, скажем, по крайней мере с сотой доли секунды, если вы хотите использовать его для прогнозирования позиций игрока. Системные часы никогда не будут так хорошо коррелированы между случайными машинами. Таким образом, вы должны установить корреляцию самостоятельно, используя некоторые вариации на тему NTP , возможно, встроенные в другие ваши сообщения, чтобы сохранить пропускную способность сети.
Основная идея может заключаться в том, что для каждого пакета, который вы отправили, вы отправили метку времени, порядковый номер и метку времени, когда вы получили последний пакет с другой стороны. Исходя из этого, вы вычисляете туда и обратно: например, если пакет Q говорит, что он был отправлен в 1000, а пакет P был получен в 500, чем, если вы отправили пакет P в 0 и получаете Q в 800, обратное путешествие равно (800 - 0 ) - (1000 - 500) = 300. Нет возможности узнать ассиметрию, поэтому вы просто предполагаете, что пакет занимает половину (150) тактов в любом направлении. И эта удаленная временная метка опережает локальную на 1000 - (800 - 150) = 350 тиков. В оба конца будет меняться. Если вы предполагаете, что часы достаточно точны, вы должны использовать долгосрочное среднее значение корреляции.
Обратите внимание, что вы не хотите использовать системные часы для часов. Они могут быть повторно синхронизированы на полпути, сбивая вас с пути. Вы должны использовать
clock(CLOCK_MONOTONIC)
в Unix илиGetTickCount
в Windows (не знаю, как эти API обернуты сейчас в Java или Python).Примечание. Параметр
SO_TIMESTAMP
сокета (см. Socket (7), упомянутый ott-- в комментарии к вопросу) будет полезен для выделения эффекта задержки цикла обработки событий, который получает пакеты. Стоит ли это усилий, зависит от того, насколько хорошая точность вам нужна.источник
Как узнать, какие часы у игрока правильные? Вы не делаете, так что используйте опорные часы .
NTP здесь излишний - вам нужна точность всего ~ 1 секунды, поэтому используйте rdate или выберите один из многих алгоритмов синхронизации часов.
После того, как вы выбрали метод, попросите машину каждого игрока подобрать время для этого метода (без изменения их системных часов). Какая бы разница между эталонным временем UTC и временем UTC системных часов игроков, это их эффективное смещение. Каждый раз, когда вы делаете расчеты, связанные со временем, например, для экстраполяции движений ботов или трассировки лучей, вы учитываете это смещение после получения системного времени. Использование UTC устранит факторы часового пояса.
источник
Во-вторых, я утверждаю, что вы не должны использовать NTP или приближаться к системным часам для этого. Если вы действительно изучите это требование, вы обнаружите, что у вас есть следующие потребности:
Это упрощенная схема - я не пытаюсь иметь дело с такими проблемами, как задержка / отброшенные пакеты / и т. Д. - но это базовая структура, на которой все это должно базироваться
Ничто из этого не должно приближаться к системным часам или заниматься такими вопросами, как различные часовые пояса, хотя последний элемент может использовать часовой пояс, если это необходимо. Важно то, что фактическое истекшее время измеряется с использованием таймера высокого разрешения, основанного на нуле, поэтому они абсолютно не зависят от различий часовых поясов. Хотите узнать текущее время на сервере? Просто добавьте истекшее время к своему базовому времени, и вы его получите. Аналогично для клиента.
источник