PDA

Просмотр полной версии : realtime передача координат


Фенёк
14.11.2013, 16:34
Доброго всем дня, давеча столкнулся с такой проблемой:

С товарищем напару пишем онлайн игрушку. Решили использовать TCP протокол для передачи данных, после чего сразу же стали наступать на всевозможные неприятности при его использовании, как то, например отправка нескольких "пакетов" одной большой пачкой в склеенном виде.

Решение для этой проблемы нашлось довольно быстро: стали просто обозначать заголовки у пакетов, после чего "слипшиеся" фрагменты пакетов перестали представлять собой проблему.

На клиенте я реализовал таймер той же длительности, что и время цикла отправки сообщений на сервере. Итого, раз в определенный промежуток времени, я просто вычитываю из потока пакет. вся фигня в том, что иногда в поток пакет еще не пришел целиком и клиент продолжает ждать, до следующего тика, пока пакет не будет собран полностью, вследствие чего игрок на поле постоянно "дрыгается".

Занятная закономерность состоит в том, что если клиент постоянно посылает серверу данные, то получает он их в ответ с меньшей задержкой.

как вылечить багу?

Котяра
14.11.2013, 17:06
Передавать "слепок мира" - плохая идея.

C4Grey
14.11.2013, 18:27
Какой-то старнный алгоритм чтения данных, Socket позвояет подписаться на событие ProgressEvent.SOCKET_DATA, в нем и нужно считывать данные, таймер не нужен. Что касается рассинхронизаций - в одно время долго пытался наладить синхронизацию клиентов в р2р-сети, к сожалению, так и не удалось достичь необходимого урвоня детерминированности игрового мира - уж не знаю, Flash тому виной, или я недостаточно постиг дзен, но, как мне кажется, для Flash-клиента такой метод не подходит - в силу низкой точности таймеров и вычислений. Потому перешел на иерархическую клиент-серверную архитектуру, где все расчёты игрового мира проводит сервер, выдавая клиентам только информацию об изменениях. Но и с этим архитектурным решением порой появляются проблемы с синхронизацией, впрочем, это уже пробелмы реализации.
Реализацией своего протокола не заморачивался, есть готовые библиотеки для работы с AMF(по крайней мере, под Java и C# - точно есть), очень удобный формат, использую его даже для клиент-серверных приложений без использования Flash(в качестве альтернативы можно посмотреть protobuf). Если есть проблемы с буферизацией сообщений(т.н. "слипание"), советую проверить, реализована ли очискта буфера исходящего потока на сервере после записи сообщения(обычно это метод flush).

P.S. Когда-то на форуме проскакивала ссылка на 2D игрушку, а-ля Quake, автором которой, если не ошибаюсь, являлся кто-то из завсегдатаев flasher.ru. К сожалению, не могу найти ссылку, но это была единственная игрушка на AS, в которой был нормально реализован real-time multiplayer, по крайней мере из тех, что я видел - возможно кто-то помнит о чем речь, и подскажет ссылку и контакты автора, буду благодарен.

bifidokk
15.11.2013, 08:56
Передавать "слепок мира" - плохая идея.

почему? сложно сделать откат, если какие-то данные из всей "пачки" не пройдут?

Gaen
15.11.2013, 14:32
Прочитайте вот этот цикл статей по программированию сети для реалтаймовых игр, там вы наверняка найдете все необходимые ответы:

http://www.gamedev.ru/code/articles/?id=4262
http://www.gamedev.ru/code/articles/?id=4261
http://www.gamedev.ru/code/articles/?id=4260
http://www.gamedev.ru/code/articles/?id=4259

вот еще просто и понятно про интерполяцию координат для сглаживания задержек, это пожалуй даже больше по теме
http://www.ant-karlov.ru/PlayerIO-interpolyatsiya-ili-udivitelniy-mir-obmana.html
http://www.ant-karlov.ru/PlayerIO-reshenie-problemi-zaderzhek.html

Фенёк
15.11.2013, 17:22
Ага, ок, спасибо за статьи, почитаю, отпишусь. На данный момент времени практически удалось довести приведенный мною способ до ума

----
UPD Вобщем отчитываюсь:

Таки алгоритм удалось настроить так, чтобы действия были плавными.

Механизм не странный, просто решили сформировать свой бинарный протокол передачи данных, с целью уменьшения объема пересылаемых данных.

Поскольку TCP протокол так устроен, что отправляет данные кусками размеры которых определяет сам, иногда происходило склеивание информации, то есть за один раз(то есть, например, сервер раз в 100 мс хочет отправлять данные, но протокол их не отправляет(по какой-то еще не известной мне причине), зато отправляет их на следующую итерацию вместе с данными сформированными на текущей итерации), мне могло прийти две итерации перемещения игрока. Тогда мы стали дорисовывать данным заголовок и конец, разделяя их таким образом на пакеты. соотвественно вычитывать за один раз сразу обе итерации перемещения персонажа не имеет смысла, был создан таймер, который раз в определенное время доставал из потока пакет и обрабатывал его, пока остальные данные в пути.

вобщем получилось сбивчиво несколько.

И да, почему передавать слепок мира плохо?

Hauts
22.11.2013, 16:43
И да, почему передавать слепок мира плохо?

— нерационально. Лучше передавать изменения.

caseyryan
22.11.2013, 17:48
— нерационально. Лучше передавать изменения.
Все время - да. Но время от времени нужно и слепок передавать. Чтобы наверняка все расхождения подкорректировать

Hauts
22.11.2013, 18:38
caseyryan, да, конечно.

Я не упомянул про это надеясь на то, что это будет очевидным, как сделают передачу изменений :)