On-line игры: взаимодействие с сервером (на примере игры MOBL от компании K-D LAB).
Автор: Алексей Шакин
(2game || !2game) ? doGame() : playGame()
Краткое предисловие
Оn-line игры, их типы. Функциональность сервера
Программирование взаимодействия с сервером
Реализация взаимодействия: игровой клиент
Заключение
Приложение А: кратко о проекте MOBL
Приложение B. Глоссарий.
Краткое предисловие
или небольшое неформальное введение в тему...
Многие современные игры немыслимы без поддержки сетевой игры. Случилось так, что даже в простейших абстрактных логических игрушках были слегка изменены с целью поддержания работы с сервером и режима сетевой игры. Даже в играх, рассчитанных на одного игрока, предоставляется возможность сохранить свои достижения в таблице рекордов на сервере. Достигается это взаимодействием самой игры и игрового сервера.
Из всего множества современных игр мы выделим и подвергнем небольшому анализу on-line игры. Если быть еще более точными, то мы с Вами разберем общие вопросы взаимодействия между однопользовательским игровым клиентом и игровым сервером. В качестве наглядного примера рассмотрим реализацию подобного общения в "симуляторе жизни" MOBL (официальная страница продукта) компании K-D LAB. MOBL представляет собой WEB приложение, в котором серверная часть реализована на JSP, а клиентом выступает апплет.
Автор, избегая приведения <однозначных> рецептов вида: <чтобы получить ЭТО, сделайте ТО>, старался выдержать данную статью в стиле <как это делалось>, рассматривая один из возможных вариантов решения поставленной задачи. В процессе изложения не заостряется особое внимание на вопросах конкретной реализации, однако большинство приводимых примеров потребуют от читателя некоторых знаний языка программирования Java в целом и технологии JSP, в частности.
Оn-line игры, их типы. Функциональность сервера
Для начала давайте определимся с терминологией и дадим несколько общих определений для таких понятий как игровой клиент, сервер и взаимодействие с ним.
Под on-line игрой мы будем понимать небольшую (порядка нескольких сотен килобайт) игровую программу, которая загружается с WWW-сервера, и требующая наличия соединения (возможно, непостоянного) со своим игровым сервером. Понятно, что чем меньше размер нашей игры, тем лучше, так как это позволяет увеличить количество наших потенциальных игроков за счет тех пользователей, которые являются "счастливыми" обладателями достаточно медленных каналов связи. Игра может быть реализована в виде апплета (Java) или при помощи Flash (Macromedia). Никаких ограничений на жанровую принадлежность не накладывается - наша игра может быть как небольшой обычной аркадой, так и стильной мозгодробильной головоломкой. On-line игры делятся на однопользовательские (игрок может играть только самостоятельно) и многопользовательские (игрок играет совместно с другими пользователями или против других игроков). Обращаю Ваше внимание на то, что подобное разделение игр, в общем случае, никак не влияет на количество одновременно играющих пользователей на одном игровом сервере.
Игровым сервером назовём [url=#webapp]WEB-приложение[/url], которое является программной реализацией следующей функциональности:
1. первичная регистрация пользователя- игрока в системе;
2. проведение проверок регистрационных данных при подключении зарегистрированных игроков;
3. взаимодействие с игровым клиентом (в основном, обмен требуемой для игры информацией, в соответствии с заданным внутренним протоколом);
4. хранение всей необходимой для игроков и игр информации в некоторой БД и предоставление доступа к ней.
На "плечи" сервера могут быть возложены и другие задачи. Реализация сервера, понятное дело, может быть выполнена на любом известном вам языке программирования и с дополнительным применением полезных технологий и будет представлять собою набор серверных сценариев (JSP, ASP, etc.)
Загруженный с сервера экземпляр игры (либо в браузер пользователя, либо сохраненный локально в файловой системе) является клиентом по отношению к игровому серверу. При этом взаимодействием между клиентом и сервером мы называем процесс обмена сообщениями между экземпляром игры и игровым сервером в соответствии с неким внутренним протоколом. Так же как и в случае с размером игрового клиента, следует уменьшить объемы передаваемых данных между клиентом и сервером.
Программирование взаимодействия с сервером
Приступим же к рассмотрению вопросов реализации (здесь и далее будет использоваться Java/JSP). В общем случае происходит следующее:
1. пользователь регистрируется на сервере;
2. зарегистрированный пользователь авторизуется на специальной страничке доступа к игре;
3. сервер подготавливает клиента-игру для сеанса;
4. игра, с компьютера клиента, время от времени ведет информационный обмен с сервером.
Регистрация пользователя. Проверка регистрационных данных.
Наш MOBL-сервер является обычным WEB-приложением. Было решено сделать регистрацию игроков и проверку регистрационных данных (при открытии пользователем игровой сессии) независимой от самого игрового клиента. Пользователю нужно заполнить регистрационную форму (см. Листинг 1; также см. формы HTML). Проверка корректности вводимых данных осуществляется на клиенте при помощи javascript-a. Такая же проверка осуществляется и при получении данных формы серверным сценарием регистрации. Отмечу, что приводимый в листинге код сильно упрощен и сокращен. Сделано это было для того, чтобы не загромождать изложение деталями JSP-реализации. Серверный сценарий регистрации, в случае корректности полученных регистрационных данных, осуществляет добавление нового игрока в свою базу данных. Кстати, применение СУБД и, как следствие, использование SQL для работы с информацией в БД, не только упрощает процесс разработки, но и повышает переносимость кода.
ЛИСТИНГ 1.
Регистрационная форма игрока
<form name="RegForm" action="reg" method="post" onSubmit="return ParseRegForm();"> <table align="center" cellpadding="0" cellspacing="0" border="0"> <tr> <td align="right"><font size=3>Ник:</font></td> <td><input class="in" type="text" SIZE="10" name="nick" maxlength="20"></td> </tr> <!-- ... здесь определяются другие поля для регистрации ... --> <tr> <td></td> <td><input class="on" type="submit" value="Зарегистрироваться!"></td> </tr> </table> </form>
Проверка регистрационных данных, при подключении зарегистрированного игрока, не представляет особой сложности в реализации. В общем случае, для этого достаточно предоставить игроку небольшую регистрационную форму на серверной странице для ввода логина.
Взаимодействие клиента и сервера. Определение протокола.
Очевидно, что для нормальной работы игры одной регистрации на сервере будет недостаточно и потребуется обмен данными между клиентом и сервером.
Начав разработку WEB реализации, было бы логичным рассмотреть взаимодействие между клиентом и сервером, основываясь на применении HTTP-протокола (RFC2616). Это позволяет не задумываться о всевозможных сетевых программно-аппаратных конфигурациях, через которые могут <пролетать> наши пакеты. В результате мы получаем возможность играть с любой машины, на которой есть установленный и нормально настроенный для WEB-сёрфинга браузер.
Исходя из вышесказанного, получаем: (*)
· запросы от игровых клиентов обрабатываются серверными сценариями;
· вся требуемая информация передается сценариям через набор параметров. В частности, т.к. HTTP-протокол является пассивным, каждое обращение нашего игрового клиента должно передавать на сервер данные о текущем игроке;
· серверные ответы формируются в plain-тексте (в заранее определенном нами формате), и разбираются на клиенте. Сервер и клиент "знают" о требуемом формате сообщений и в каждом конкретном случае способны корректно обработать их.
MOBL-клиент является Java-апплетом, требующим для нормального функционирования игры периодического подключения к серверу для загрузки/сохранения игровой информации. Апплет должен знать о своем текущем игроке. Следовательно, сервер должен каким-то образом предоставить данную информацию апплету (желательно побеспокоиться о том, чтобы пароль не <летал> в открытом виде, в противном случае велика вероятность того, что Вам чего-то да <поломают>). К счастью, нам не нужно в данном вопросе изобретать велосипед и воспользуемся стандартным решением - передача параметров в апплет (см. Листинг 2). Кстати, использование элемента APPLET уже устарело, вместо него рекомендуется использовать элемент OBJECT.
Имеем следующее: после удачной регистрации, сервер генерирует <на лету> HTML-страничку, в которой есть информация о самой игре (апплет), и данные текущего игрока, переданные в апплет в качестве параметров. Так как во время создания второй версии MOBL-а была включена поддержка русского языка (первая версия была исключительно английской), в апплет также передается информация о выбранном пользователем языке.
ЛИСТИНГ 2.
Передача регистрационных данных в апплет
<applet name="Mobl" width="640" height="480" codebase=".." archive="mobl.jar" code="com.kdlab.mobl.applet.Mobl.class" > <!-- тут были другие параметры --> <param name="nick" value="тут должен быть Ник игрока"> <param name="password" value="понятное дело, что пароль, закрытый"> <param name="lang" value="или RU, или EN"> </applet>
Также нам на сервере нужны сценарии для взаимодействия с клиентскими апплетами, а именно:
· получение исходных данных для начала новой игры;
· сохранение на сервере результатов игры;
· загрузка игровых данных для просмотра сохраненной игры.
Реализация взаимодействия: серверная часть.
Очевидно, что реализация серверных сценариев (отвечающих за взаимодействие с игровыми клиентами) не представляет большой сложности, так как укладывается в рамки задачи разработки WEB приложений.
Кратко рассмотрим функциональность этих сценариев, на примере кода сценария создания новой игры и генерации стартовых параметров (см. Листинг 3). В начале каждый сценарий должен осуществить проверку правильности переданных ему регистрационных данных (отмечено на листинге при помощи reg-check). Если регистрационные данные корректны, сценарий начинает выполнение запрошенной функциональности, в нашем примере - простая генерация стартовых параметров для новой игры (create). Затем сценарий формирует ответ для клиента (answer). Отметим, что из-за использования HTTP, каждый ответ игрового сервера (выдаваемый обычным plain-текстом) будет дополняться со стороны WEB-контейнера стандартным HTTP-заголовком. Поэтому, для облегчения разбора серверного ответа на клиентской стороне, начало вывода серверного ответа предваряется `init`-тэгом, обозначающим место окончания HTTP-заголовка (init).
Реализация функциональности серверных сценариев для сохранения/загрузки выполняется аналогично рассмотренному выше материалу.
ЛИСТИНГ 3.
Создание новой игры и генерация стартовых параметров