2013-08-03 3 views
2

Прежде всего, я хотел бы извиниться за мой плохой английский :) Вчера я закончил писать свою первую многопользовательскую игру (понг) на C++ с помощью Winsock и Allegro5. Игра состоит из одного сервера для всех игроков и клиентов.Почему запаздывание противника в моей игре в многопользовательском понге?

Каждый клиент кадра (FPS = 60) отправляет свои координаты mouse_y на сервер, который передает их клиентам своих оппонентов соответственно. Когда я играю в игру на своих двух компьютерах, подключающихся к серверу, который работает на одном из них, по локальной сети он отлично работает, весло оппонента движется плавно. Но когда я делаю то же самое подключение через мой внешний IP-адрес, лопасть противника отстает, что разрушает игру, потому что это клиент, который проверяет, попал ли мяч в лопатку противника или нет. Таким образом, синхронизация разрушена, всякий раз, когда я перемещаю один весло, чтобы отскакивать мяч на другом компьютере, он отстает и не делает это вовремя, что приводит к забиванию точки для противника ... Но это не игра, которая отстает. Мои весла и мяч движутся плавно. Проблема только в веслах противника.

Я новичок в сетевом программировании, поскольку я только читал Beej's Guide to Network Programming. Я использую TCP-сокеты для отправки() и recv() координат весла и функции select() для опроса сокетов для данных.

У меня нет ни единой идеи, что может быть причиной.

TL; DR: Весы протектора отстают, когда я подключаюсь через внешний IP-адрес, но не при подключении через локальный IP-адрес.

ответ

2

Чтобы расширить то, что сказал Томас. Я собираюсь дать вам немного более практичный ответ.

  • Используйте UDP для игр.


Если вы настаиваете на использовании TCP, то сделать это.

  • Lower значение TcpAckFrequency.

  • Отключить алгоритм nagle, потому что ваши запросы будут небольшими по размеру. Сделайте это, установив TCPNoDelay на 1.

  • Простота перемещения между двумя точками.

  • Пошлите меньше данных при упаковке остальных.

  • Передача полученных пакетов в структуры.

  • Не использовать select. После 50 или около того вы заметите huge потери производительности. Используйте epoll или IOCP для Windows/Linux соответственно.

+0

Если я сменил TCP-сокеты на UDP, действительно ли это ускорит передачу данных до такой степени, что игра будет воспроизводиться? – user2648421

+0

@ пользователь2648421 Да, * почти *. TCP не подходит для игр. Также руководство Beej не подходит для игр. Вы должны купить книгу, связанную с многопользовательскими играми, и использовать страницы руководства для таких функций, как sendto/recvfrom. –

+0

@ user2648421 Руководство Beej смутит вас. Особенно в окнах, где 'select' - всего лишь плохая идея. –

2

Ну, это вполне ожидаемое поведение, наложенное (среди прочего) на скорость света. Пакеты, передаваемые через Интернет, просто занять некоторое время, чтобы прибыть:

$ ping stackoverflow.com 
PING stackoverflow.com (198.252.206.16) 56(84) bytes of data. 
64 bytes from stackoverflow.com (198.252.206.16): icmp_req=1 ttl=53 time=85.1 ms 

Это говорит мне о RTT (время прохождения) от моей машины stackoverflow.com 85 миллисекунд, что нормально для веб-сайта, но достаточно чтобы привести к заметному отставанию в игре в реальном времени.

Плохая новость. Худшая новость заключается в том, что это очень трудная проблема.

Профессиональные многопользовательские игры в режиме реального времени используют несколько трюков, чтобы сделать отставание менее заметным. Например, они отслеживают задержку для каждого клиента и пытаются «предсказать», где игрок будет в текущий момент времени, даже если эти пакеты еще не наступили. Но, конечно, если пакеты прибывают, и предсказание оказывается неправильным, это приведет к тому, что игрок внезапно «прыгнет» в нужное место. Чтобы обойти это, они применяют некоторое сглаживание между предсказанным и последним известным местоположением. Если все сделано хорошо, это создает иллюзию движения в реальном времени.

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