Прежде всего, я хотел бы извиниться за мой плохой английский 🙂
Вчера я закончил писать свою первую многопользовательскую игру (Pong) на C ++, используя Winsock и Allegro5. Игра состоит из одного сервера для всех игроков и клиентов.
Каждый кадр (FPS = 60) клиенты отправляют свои координаты mouse_y на сервер, который передает их клиентам своих оппонентов соответственно. Когда я играю в игру на двух моих компьютерах, подключающихся к серверу, который работает на одном из них, по локальной сети он работает отлично, весло противника движется плавно. Но когда я делаю то же самое, подключаясь через свой внешний IP-адрес, весло противника отстает, что портит игру, потому что это клиент, который проверяет, попал ли мяч в весло противника или нет. Таким образом, синхронизация разрушается, и когда я перемещаю одно весло, чтобы отскочить от мяча на другом компьютере, он отстает и не успевает вовремя, что приводит к выигрышу у соперника … Но это не игра, которая отстает. Мое весло и мяч движутся плавно. Проблема только с веслом противника.
Я новичок в сетевом программировании, так как я только прочитал Руководство Биджа по сетевому программированию.
Я использую сокеты TCP для отправки () и recv () координат весла и функции select () для опроса сокетов для данных.
Я понятия не имею, в чем может быть причина.
TL; DR: весло оппонента отстает, когда я соединяюсь через внешний IP, но не когда я соединяюсь через локальный IP.
Чтобы расширить то, что сказал Томас. Я дам тебе более практичный ответ.
Если вы настаиваете на использовании TCP, сделайте это.
Понизьте значение TcpAckFrequency.
запрещать Нэйгла алгоритм, потому что ваши запросы будут небольшими по размеру. Сделайте это, установив TCPNoDelay до 1.
Облегчить движение между двумя точками.
Отправьте меньше данных при упаковке остальных.
Приведите полученные пакеты в структуры.
Не использовать select
, Примерно через 50 или около того подключений вы заметите huge
потеря производительности. использование epoll
или же IOCP
для Windows / Linux соответственно.
Ну, это совершенно ожидаемое поведение, навязанное (среди прочего) скоростью света. Посылки, отправленные через Интернет, занимают некоторое время:
$ 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 миллисекунд, что хорошо для веб-сайта, но этого достаточно, чтобы привести к заметному отставанию в игре в реальном времени.
Это плохие новости. Хуже всего то, что решить эту проблему очень сложно.
Профессиональные многопользовательские игры в реальном времени используют несколько приемов, чтобы сделать отставание менее заметным. Например, они отслеживают задержку для каждого клиента и пытаются «предсказать», где игрок будет находиться в текущий момент времени, даже если эти пакеты еще не поступили. Но, конечно, если пакеты прибывают и прогноз оказывается неверным, это может привести к тому, что игрок внезапно «прыгнет» в нужное место. Чтобы обойти это, они применяют некоторое сглаживание между предсказанным и последним известным местоположением. Если все сделано хорошо, это создает иллюзию движения в реальном времени.
Другая проблема заключается в том, что вы не можете выполнять свою игровую логику исключительно на клиенте, потому что у каждого клиента немного другое представление о мире. Это нормально, когда клиент делает прогнозы, но сервер должен сказать окончательно, ударил ли ракетка по мячу.