Почему весло соперника отстает в моей многопользовательской игре в понг?

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

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

Я новичок в сетевом программировании, так как я только прочитал Руководство Биджа по сетевому программированию.
Я использую сокеты TCP для отправки () и recv () координат весла и функции select () для опроса сокетов для данных.

Я понятия не имею, в чем может быть причина.

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

2

Решение

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

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

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

  • Понизьте значение TcpAckFrequency.

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

  • Облегчить движение между двумя точками.

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

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

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

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 миллисекунд, что хорошо для веб-сайта, но этого достаточно, чтобы привести к заметному отставанию в игре в реальном времени.

Это плохие новости. Хуже всего то, что решить эту проблему очень сложно.

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

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

2

По вопросам рекламы [email protected]