2013-08-07 2 views
-1

У меня есть общий вопрос о программировании взаимодействия клиент/сервер в сетевой игре. Я использую протокол TCP как протокол, и связь ... работает, но я не уверен, если это эффективный способ.GAMEPROGRAMMING Клиент/сервер связи через ....? (JAVA)

В целом, действия, которые происходят на стороне клиента будет идти Повсеместно все эти шаги: (. Например Fireball отливают)

  1. Некоторые действия
  2. [*] Для этого действия я определен (например, # F # 270 # 130 #, что означает, что «F» говорит, что это огненный шар, а 270 - это (например) степень угла, 130 - скорость огненного шара, который снимается.)
  3. Строка переходит в выходной буфер клиента & waitingqueue
  4. Строка отправлена ​​
  5. String принимается сервером
  6. [*] Серверу нужен интерпретатор строк, который может определять значение строки (здесь: что означает F? Это огненный шар!) & добавляет уникальный идентификатор, на основе которого, из которого клиент получил команду.
  7. [*] Серверу необходимо рассчитать логику, основанную на действии (огненный шар наносит урон кому-либо, ударяет кого-то (сразу) или просто летает первым?)
  8. Сервер отправляет (обновленную) строку действий (-ов), которые происходят для всех клиентов. (например, возможно, огненный шар замедляется по скорости по какой-либо причине - здесь будет обновленная строка (# F # 12345 # 270 # 90 # - 12345 - уникальный идентификатор игрока)
  9. клиентов получают строку
  10. [* ] клиенты разрешают строку команде + обрабатывают ее (загорать анимациюследующую информацию ...)
  11. клиент, который отправил исходную команду, сравнивает полученную строку со строкой в ​​очереди ожидания - при равных значениях ничего не делать (чтобы сгладить какое-либо действие, иначе через соединение проблемы/задержки, некоторые действия будут происходить дважды или перейти от места к местоположению на основе ping

Действительно ли необходимо пройти все t hese шаги? На всех шагах, отмеченных значком [*], мне нужно определить новые интерпретаторы строк/действия для каждой команды, поэтому я кодирую каждое действие дважды, клиентский сервер &. Я читал что-то о передаче сериализуемых объектов, но в генетическом смысле идея кажется мне одинаковой, я отправляю объект, который должен интерпретироваться + обрабатываться, и я отправляю объект обратно ...

Любые подсказки? Чтобы решить все общение более элегантно, с меньшей кодировкой? Или немного больше отсортированы - все эти # F # # M # # H # теги для различных действий, делает его более сложным :)

(На самом деле я на самом деле имею следующие обработчик/действия:

- двигаться -Смотри/вращать -hpchange -firearrow -spawn/разъединение ...)

Надеюсь, вы понимаете, что я имею в виду - я знаю, я мог бы просто продолжать кодирование, как это, и он будет работать как-то, но это кажется слишком сложным, как могло бы быть.

Спасибо!

+0

Есть еще больше :) String отправляется, Bytes передаются на сервер, String принимается сервером, а остальные 100 шагов вы не указали – Tala

ответ

0

Вам необходимо изучить несколько факторов, прежде чем вы решите, требует ли ваша игра каких-либо изменений.

Во-первых, является ли TCP лучшим каналом связи? Вы сравнили это с UDP. Было бы лучше реализовать сеть с использованием UDP? Не имеет значения, пропало ли несколько пакетов? Что происходит, если сеть работает медленно?

Во-вторых, посмотрите, как часто вы проводите опрос/нажатие на сервер. Можно ли это уменьшить? Должна ли игра быть в режиме реального времени. Все части игры должны быть в режиме реального времени. Возможно, некоторые вещи могут быть нереальными. Огненный шар будет продолжаться по прямому пути, поэтому вам не нужно постоянно обновлять сервер о его положении, вы можете просто рассказать о его направлении и скорости. Какие другие аспекты игры могут быть не в режиме реального времени. Единственное, что нужно отправить, это расположение игроков и действия. Большинство других вещей, таких как обнаружение столкновения, могут быть выгружены клиенту.

В-третьих, нужно ли каждое нажатие клавиши отправлять на сервер? Если пользователь выступает против стены и хочет двигаться дальше, клиент знает, что он не может и, следовательно, не будет отправлять эти нажатия на сервер. Если пользователь переместился в новое допустимое местоположение, обновите сервер. Можно ли буферизовать определенные вещи и отправлять их на сервер за один раз, вместо отправки нескольких запросов на сервер. то есть, если я двигаюсь вперед, прыгаю и бросаю огненный шар, то есть 3 нажатия клавиши на стороне клиента, могут ли они быть буферизованы и отправлены на следующей 500-й миллисекунде?

Если вы обеспокоены сетевыми издержками, вы должны работать на уровне бит. Вместо отправки длинной строки «# F # 270 # 130 #» - длиной 11 байт, было бы целесообразно отправить 3 последовательных байта (24 бит).

7 бит представляют собой действие (127 различных действий). 9 бит будут представлять угол (1-512), но вам нужно только до 0-360 градусов. 8 бит представляют силу.

Этот или любой другой формат байта короче и проще в использовании по сети и создает более строгий код. Кроме того, бинарное сравнение выполняется быстрее, поэтому упростить создание анализатора действий на сервере. То есть вместо большого случая переключения, ищущего # F #, вы просто смотрите на первые 7 бит и сравниваете его с int.

Можете ли вы уменьшить другие сетевые накладные расходы, а не силу, решаемую клиентом, может ли сервер решить это. то есть стандартную силу или 2 уровня силы (намного лучше, чем это может быть представлено 1 бит).Что останавливает клиента и вредоносных пользователей, отправляющих данные мусора на сервер (например, сила 999), теперь сила может быть либо 0, либо 1, то есть скоростью 10 или 20, ничто глупо.

+0

Хорошо, это звучит очень полезно, насколько мне известно, самые известные многопользовательские игры (RealTimeStrategy ... Starcraft?, Не знаю точно, но World of Warcraft?) Используют UDP, но я не могу представить, как обрабатывать недостающую информацию, Я имею в виду, что почти каждое действие имеет значение или может иметь значение. Каждый отправленный объект мог быть близким к смертельному исцелению. Мне нравится часть об уменьшении трафика, но я не думаю, что дойду до тяжелого движения с помощью моей маленькой игры: D Он будет обрабатывать, не знаю, может быть, до 5 игроков и ~ 50 других движущихся объектов. В настоящий момент действия буферизуются в стеках 50 мс ... –

+0

Возможно, ваши сообщения могут быть отправлены с несколькими байтами, представляющими идентификатор сообщения. Каждый клиент будет иметь свою собственную очередь отправленных сообщений и полученных сообщений. И они последовательны, поэтому 00000001 и 00000010 и т. Д. Постоянно увеличивают (и, в конечном счете, перезагружают), поэтому вы можете сохранить дорожку. Если сервер или клиент когда-либо видит сообщение не в последовательности, он будет знать, что сообщение было потеряно при переходе. – Husman

1

Вы можете сделать это в более OO способом, если вы:

  1. Определить объект под названием Action или что-то подобное, который имеет все вышеперечисленные параметры - тип действия, направление действия (или цель), урон, и т.д ..
  2. Создать эти объекты действий как ваша игра обычно выполняет
  3. Использование ObjectOutputStream прикован к вашему TPC Разъем для вывода весь объект действий на сервер/передать его обратно клиенту.
  4. На сервере интерпретируйте, что происходит, исследуя полученный объект из ObjectInputStream.

Я думаю, что этот путь будет чист и более гибким, в случае, если добавить больше логики, чем просто анализирующие строки, но не так быстро (так как объекты, поступающие в ObjectOutputStream должны быть сериализованным).

+0

Хорошо, это звучит так, как я читал. Но да, это было бы более элегантно :) Я думаю, что я отредактирую свой код на этот вариант и определю абстрактный класс действия, а также многие классы субакций, которые будут описывать действия ... возможно ли определить методы в классе , fe doLogic(), а затем после отправки на сервер и обратно, вызовите их? например. action.doLogic(), и они будут обновлять некоторые параметры игры? Это невероятно поможет! ^^ –

+0

Да, его можно определить методы, в основном вы можете передать любой нормальный класс, если у него нет ссылок на внешние вещи - например. ссылки на файл или на базу данных и т. д. Если это так, эти переменные экземпляра, представляющие ссылки, должны быть отмечены переходным процессом модификатора, чтобы они не были сериализованы. Вы можете прочитать немного больше о том, когда использовать переходный процесс здесь: http://stackoverflow.com/questions/5960280/what-is-the-use-of-transient-variables Надеюсь, что это поможет, удачи! –

Смежные вопросы