Клиент-серверная архитектура казуальных сетевых игр

Добрый день. В данной статье я постараюсь дать общий очерк о роли сервера и пинга в анимации для казуальных игр. В статье вся информация представлена с уклоном в казуальные игры с TCP протоколами, в крупных коммерческих проектах часто используются UDP+TCP протоколы, и лайфхаков у них куда больше.

Очевидно, что в онлайн-играх, помимо игрока, участвует ещё сервер. Сервер это такая шайтан-машинка, для настройки которой нужны деньги и квалифицированные специалисты, именно серверу мы будем доверять обработку игрового процесса. Игроку с сервером нужно как то обмениваться данными, давайте поговорим об этом.

Рассмотрим протокол P2P. Под Peer-To-Peer (P2P) архитектурой подразумевается, что каждый из компьютеров подключается к общей сети, и каждый компьютер имеет контроль над данными игры. Другими словами, P2P это полное отсутствие безопасности. Здесь возможна и подмена данных, и несогласованность между двумя пирами. Конечно, P2P не является мракобесьем, и эта технология имеет место быть в некоторых случаях, например для игры в крестики-нолики без сервера, но по факту, P2P годится только для игр с небольшой продолжительностью игровой сессии и небольшим количеством одновременно играющих игроков в одной сессии. Сразу сделаю поправку, что на территории РФ и постсоветского пространства у очень большого количества геймеров установлены всякие MonsterDebugger и прочие читерские программы для извлечения и подмены данных, и разработчику приходится организовывать дополнительные методы защиты. Но защитить то, что находится на компьютере пользователя, очень сложно. Как же быть?

Просто! Всю работу с компьютера игрока мы сбросим на сервер, именно он будет обрабатывать действия игроков и просто рассылать результаты своей работы, это и называется клиент-серверной архитектурой.

Так как в прошлом, а иногда и в настоящем я флешер, то рассмотрим способы обмена данных с сервером на примере разработки флеш-игр (да, флеш не умеет использовать ничего, кроме TCP протоколов : )). Для начала зададимся самым жизненным вопросом современного школьника: как можно взломать игру на флеше? Перекомпилировать. Или использовать альтернативные Flash-клиенты с изменённым функционалом, или даже шестнадцатеричное редактирование. Но вся необходимая для игры информация обрабатывается на сервере! В таком случае атака на клиент нашей игры фактически бесполезна, он не имеет особой ценности, будучи программой только для демонстрации игрового процесса. Клиент отправляет сообщения серверу и при этом не имеет особого влияния на игровую логику. Итак, чтобы обеспечить безопасность, желательно все вычисления проводить на стороне сервера. Это ясно.

Но в таком случае появляется пинг. Пинг это время, которое тратит сообщение на путь от клиента к серверу и обратно. И по честному исправить ситуацию невозможно. Как результат, задержка добавляет игре дёрганности и прочих лагов. В быстрых играх, если игрок за 200мс пробежит 5 метров, то при лаге в 200мс игрок телепортируется на 5 метров. То же касается и эффектов. Если игрок наступил на мину и успел отбежать назад, но при лаге пинга эта  информация не успеет обновиться,  игрок будет отброшен взрывной волной совершенно не в ту сторону, в которую он рассчитывал. Думаю, проблема ясна.

Решить проблему установкой таска в редмайне для программистов не получится, от пинга избавиться невозможно. Но можно создать иллюзию отсутствия таких задержек. Если игрок имеет хороший пинг, менее 20 мс, то игрока вполне можно обманывать. А именно, восстановить то, что должно быть на экране у второго игрока. Попросту угадать действия игрока, и использовать интерполяцию для сглаживания анимации. Есть много способов интерполяции, начиная с обычной линейной (плавное перемещение игрока из места, где он находится в место, где он должен быть), заканчивая интерполяций на основе кубических сплайнов,  но всё это полумеры, так как время, которое тратится на передвижение игрока к нужной позиции, способно ввести в заблуждение других игроков. А ведь все проблемы, связанные с задержками, вызваны взаимодействием игроков друг с другом. На сервере есть самая актуальная информация и действии игроков, и пока сервер не скажем игровым клиентам об этих действиях, эти действия не произойдут. А предугадывание действия оставим для полёта взрывчатого снаряда, предугадывание годится только для вещей с линейным движением.

Будем ориентироваться исключительно на сервер, получать информацию о действиях игрока только с сервера, пока сервер не скажет — ничего не меняется. Но игрок будет точно недоволен несвоевременной реакцией игрового персонажа на нажатие клавиш.  Игрок банально теряет контроль над своим героем. Что делать? Брать и физически насиловать дизайнеров и аниматоров, разумеется }:  ). Пусть анимация содержит задержки, вроде торможения персонажа после бега, приседание перед прыжком, поворот оружия перед выстрелом, это позволит скрыть несовершенства клиент-серверной архитектуры.  И, как очевидно, имеет смысл сделать игру чуть медленнее, чем мечтает арт-директор, это тоже поможет дать запас времени для обмена данными с сервером.

Из оптимизации есть кое что ещё: многопользовательские игры масштабируются по функции О(n^2), где n = 128, это игроки. Один из игроков сделал ход, соответственно, всем игрокам надо об этом сообщить, и для каждого игрока придётся создать подключение. Количество передаваемой информации, как вы видите, очень высоко, нагрузка на сеть растёт. Но ведь один игрок не может видеть сразу всех 128 игроков, ни при каких обстоятельствах. Тогда количество соединений можно оптимизировать. Если из этих 128 игроков половина в нашей команде, то количество информации об их действиях также можно оптимизировать. Ведь не факт, что они способны нанести нам урон или даже врезаться в нас по идеологии игры.

Вы уже знаете, что интерполяция с линейным сглаживанием весьма неоднозначное решение, и назвать хорошим его нельзя, а вот упомянутая интерполяция с использованием кубических сплайнов выглядит более интересно. Из школьного курса математики все помнят, что линейная функция может быть представлена уравнением с переменной первой степени, например x = 5*y. В кубической функции как минимум один член возводится в степень, x = 5*y ^2. Подробнее здесь.

Есть и другие хитрости, например все знают, что в MMORPG распространено перемещение персонажа кликом по локации. А ведь это так просто! Передали информацию о том, куда надо направить персонажа и запустили анимацию, никаких проблем. Персонаж бежит, игра рисует красивую живую картину, сервер успевает отрабатывать. В крайнем случае, можно уменьшить скорость игрока на несколько процентов, что даст запас времени в несколько десятков мс и это будет незаметно для игрока.

Резюмируя, проблема синхронизации в играх — это обман, в котором участвуют и дизайнеры, и программисты. Сделать в первую очередь технически правильно и исходя из этого красиво, это и есть задача дизайнера и художника-аниматора, который работает в команде над IT проектом.

4 комментария

  1. Саша Власов

    Здравствуйте! У меня следующий вопрос: как запустить SWF на маке?