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

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

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

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

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

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


person user2648421    schedule 03.08.2013    source источник


Ответы (2)


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

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


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

  • Уменьшите значение TCPAckFrequency.

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

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

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

  • Разложите полученные пакеты в структуры.

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

person gifnoc-gkp    schedule 03.08.2013
comment
Если бы я изменил сокеты TCP на UDP, действительно ли это ускорило бы передачу данных до такой степени, что в игру можно было бы играть? - person user2648421; 03.08.2013
comment
@ user2648421 Да, почти. TCP не подходит для игр. Также руководство beej's не подходит для игр. Вам следует купить книгу по многопользовательским играм и использовать справочные страницы для таких функций, как sendto / recvfrom. - person gifnoc-gkp; 03.08.2013
comment
@ user2648421 Руководство Beej вас сильно запутает. Особенно в окнах, где select - просто плохая идея. - person gifnoc-gkp; 03.08.2013
comment
Игровая книга? Не могли бы вы порекомендовать мне один, если бы вы случайно вспомнили какой-нибудь заголовок, пожалуйста? - person user2648421; 03.08.2013
comment
@ user2648421 Для игр это хорошее место для начала, devmaster.net/categories/articles - person gifnoc-gkp; 03.08.2013

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

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

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

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

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

person Thomas    schedule 03.08.2013