Создание игр для мобильных телефонов - Майкл Моррисон
Шрифт:
Интервал:
Закладка:
Чтобы лучше понять, о чем идет речь, рассмотрим, что может случиться, если синхронизация будет утеряна. Предположим, что два человека играют в сетевую игру, аналогичную популярной игре Diablo. Например, они бегут вместе. Пробегая мимо демона, более агрессивный игрок 1 начинает с ним сражаться. У игрока 2 мало энергии, и он решает отойти в сторону и понаблюдать. Когда игрок 1 заканчивает борьбу с демоном, игрок 2 должен быть уведомлен об этом. И не только с точки зрения удобства: все изменения в игре должны быть отражены и для прочих игроков.
Другая проблема, связанная с синхронизацией, – это использование случайных чисел. В начале игры многие объекты, например, сокровища и монстры, размещаются случайным образом. Иногда в играх используются случайные события, изменяющие игру от одного запуска к другому. В сетевых играх это создает большую проблему, если на каждом телефоне не используются те же случайные числа. Все пойдет насмарку, если каждый из образов игры будет генерировать объекты случайно относительно других образов. Дело в том, что, казалось бы, такие незначительные моменты, как генерирование случайных чисел, может создать массу проблем в сетевом окружении.
Теперь, когда вы понимаете, какие проблемы могут возникать, давайте перейдем к тому, как их можно решить. Существует множество подходов к разработке сетевых соединений, каждый из которых должен каким-то образом решать проблему синхронизации. Мы рассмотрим два основных типа синхронизации сетевых игр: синхронизация состояния и синхронизация ввода.
Синхронизация состояния
Синхронизация состояния – это метод соединения, посредством которого каждый образ сетевой игры обновляет состояние в соответствии с состояниями других образов. Этот метод синхронизации очень надежен, поскольку не происходит потеря информации: все, что касается состояния игры, отправляется другим образам. Например, в космическом симуляторе для двух игроков текущим состоянием игры будет скорости и координаты всех планет, астероидов, кораблей и пуль – эта информация и будет переправляться другому образу игры.
...В копилку Игрока
Поскольку у мобильных телефонов пропускная способность сети ограничена, синхронизация состояния представляет большую сложность при реализации.
Звучит неплохо. Ну а что же будет в случае более сложной игры, например, ролевой приключенческой игры с целыми виртуальными мирами, в которых постоянно путешествуют игроки? Обмен информацией о состоянии всей игры кажется очень проблематичным, ввиду значительных объемов. И не забудьте об ограничениях скорости соединения, о которых вы узнали ранее. Вы не можете пересылать большие объемы информации между мобильными телефонами. Зная это, легко понять, что синхронизация состояний – это не лучшее сетевое решение. Хотя с точки зрения функциональности такой тип синхронизации очень хорош, с технической точки зрения он не всегда применим.
Синхронизация ввода
Синхронизация ввода – это метод соединения, при котором каждый из образов игры передает сообщения о входящих событиях другим образам игры. Используя синхронизацию ввода, каждый из игроков генерирует входные события, например, нажатия клавиш, а игра передает эти события другим играм. Если применить это к космическому симулятору, обсужденному ранее, то игра отправляет события нажатых игроком клавиш. Затем каждая запущенная игра обрабатывает эти события и вносит соответствующие изменения.
Но здесь должен быть подвох, да? Конечно, он есть! Синхронизация ввода работает хорошо до тех пор, пока изменения вносятся только игроками. Иначе говоря, в простых играх какие-либо проблемы вряд ли возникнут. В играх часто бывают случайные события, как, например, размещение фоновых объектов. Эти случайные события представляют проблему для синхронизации, поскольку они не зависят от игрока, а следовательно, их синхронизация представляет большую трудность.
Если вы разрабатываете игру, в которой все события определяются игроком, используйте синхронизацию ввода. В противном случае вы должны выбрать другой способ синхронизации. Вы можете придумать игру, в которой события генерируются только игроком? Бросьте это занятие! В итоге вы придете к пошаговым стратегиям, в которых все определяется лишь действиями игроков. Поэтому обычно синхронизация ввода применяется для пошаговых сетевых игр.
...В копилку Игрока
Игра Connect 4, которую вы разработаете в следующей главе, – это хороший пример сетевой пошаговой игры, которая полностью зависит от действий игроков.
Смешанное решение
Теперь, когда я вкратце обрисовал проблемы разработки сетевых игр, можно перейти в реальность создания мобильных игр: в большинстве случаев вам придется использовать комбинацию типов синхронизации, описанных выше. Смешанное решение будет содержать как элементы синхронизации ввода, так и элементы синхронизации состояния. Используя пример с космическим симулятором, вы можете пересылать события нажатиями на клавиши, после чего использовать синхронизацию состояния, например, для пересылки данных, скажем, о начальных координатах случайных астероидов. По-прежнему нет необходимости пересылать данные о полном состоянии игры, пересылаются только случайные данные.
Если вы столкнетесь с игровым сценарием, который нельзя реализовать посредством одной из указанных методик, вы можете разработать собственную. Сетевые игры – это уникальная область программирования, в которой есть место новым подходам. Обычно приходится использовать комбинации различных подходов на основании полученных знаний и собственных идей.
Соединение через сеть с сокетами
Несмотря на то что существует множество различных сетей, при программировании сетевых игр в MIDP используется особый тип сетевого соединения, известный как сокет (socket). Сокет – это программный элемент для входящего или исходящего соединения. Иначе говоря, сокет – это коммуникационный канал, который позволяет вам передавать данные через определенный порт. В MIDP API есть класс сокета, который значительно упрощает программирование соединений. Сокеты MIDP разделены по типам: потоковые и датаграммные.
Потоковые сокеты
Потоковый сокет (соединенный сокет) – это сокет, через который данные могут передаваться непрерывно. Говоря «непрерывно», я не имею в виду, что данные передаются в каждый момент времени. Потоковый сокет – это определенное соединение, доступное в любой момент времени. Преимущество такого сокета – это то, что информацию можно отправить, не заботясь о том, когда она дойдет до получателя. Поскольку такое соединение постоянно «активно», то дата передается немедленно в момент отправления.
Датаграммные сокеты
Другой тип сокетов, поддерживаемый Java, – это датаграммные сокеты. В отличие от потоковых сокетов, в которых соединение больше похоже на постоянное сетевое подключение, датаграммные сокеты больше похожи на коммутированное подключение, при котором соединение активно не всегда. Датаграммный сокет – это сокет, через который данные разделяются на пакеты и отправляются, при этом «активное» подключение к другому устройству не обязательно.
Вследствие различий средств соединения датаграммные сокеты не гарантируют отправление информации в определенный момент и даже в определенном порядке. Причина, по которой этот тип сокетов работает именно так, заключается в том, что им не требуется непосредственное соединение с другим компьютером – адрес устройства связывается с передаваемой информацией. Такой пакет передается в сеть, оставляя отправителю надежду, что он когда-либо дойдет до получателя. Получатель может принять отправленные данные в любой момент времени и в любом порядке. Поэтому датаграммы также содержат число, определяющее, в каком порядке должны быть расположены данные, чтобы их можно было собрать воедино. Принимающее устройство ожидает прихода всей последовательности, а затем объединяет принятые пакеты.
Вы можете подумать, что датаграммные сокеты – не идеальное средство для программирования сетевых игр, и в некоторых случаях это так. Однако не всем играм требуется «активное» соединение, обеспечиваемое потоковыми сокетами. В случае специфических мобильных игр чаще всего целесообразно использовать именно датаграммные сокеты в виду ограниченности пропускной способности сети.
...В копилку Игрока
В этой книге рассматриваются только датаграммные сокеты для установления соединения. Программированию мобильных сетевых игр можно посвятить отдельную книгу, поэтому я ограничился описанием самых простых форм мобильных сетевых игр, использующих датаграммные сокеты.
Сетевое программирование и J2ME
Сетевое программирование в мидлетах выполняется с помощью MIDP API, которое носит название Generic Connection Framework или GCF. Цель GCF – обеспечить необходимый уровень абстракции для сетевых сервисов, которые помогают различным устройствам поддерживать специальные протоколы.