Многопользовательская игра с JavaScript-интерфейсом и интерфейсом.Каковы лучшие практики? - PullRequest
37 голосов
/ 22 июня 2010

Я подумываю о создании сетевой многопользовательской игры в Node.js . Это означает, что я буду использовать один и тот же язык в бэкэнде и во внешнем интерфейсе. Это было бы в режиме реального времени и максимум 20 человек в каждой «комнате», поэтому у меня есть несколько мыслей:

  1. Как мне компенсировать задержку среди всех пользователей, чтобы все видели одно и то же в одно и то же время? Я имею в виду отслеживание среднего времени пинга для каждого игрока, поиск самого медленного и информирование других клиентов о времени (в миллисекундах), что каждый из них должен быть задержан, чтобы все были синхронизированы настолько, насколько это возможно.

  2. Я думаю о запуске игрового кода как во внутреннем интерфейсе, так и во внешнем интерфейсе (поскольку это JavaScript на обоих концах), и у меня просто есть механизм исправления ошибок для синхронизации с «реальной игрой» в бэкенд. Таким образом, игра должна работать плавно на фронтенде и с несколькими сбоями, когда происходит синхронизация. Кроме того, это минимизирует хакерство внешнего интерфейса JavaScript, так как читеры будут синхронизированы с бэкэнд-игрой.

  3. Должен ли я получать действия игрока через сокет (нажатия клавиш), информировать всех других клиентов о действиях других игроков и в то же время «играть» в игру в бэкэнде и отправлять информацию о синхронизации каждому из всех состояние игры время от времени для их синхронизации?

Что вы думаете? Есть ли еще вещи, которые я должен рассмотреть или обратить внимание?

Пожалуйста, оставляйте любые мысли или ссылки на документацию или статьи, касающиеся многопользовательских игр.


РЕДАКТИРОВАТЬ: Это полезно:

Ответы [ 7 ]

27 голосов
/ 28 июня 2010

1 - невозможно.Вы не знаете точно, сколько времени займет сообщение, чтобы прибыть на клиента, и никакие измерения не обязательно будут применимы к следующему отправляемому сообщению.Лучшее, что вы можете сделать, - это приблизительное значение, но вы всегда должны предполагать, что люди увидят ЛИБО несколько разных вещей ИЛИ одни и те же вещи в несколько разное время.Я бы порекомендовал просто отправить текущее состояние всем и использовать интерполяцию / экстраполяцию, чтобы сгладить игровой процесс, чтобы каждый видел игру через несколько миллисекунд в прошлом, причем задержка варьировалась как между игроками, так и во времени.В общем, это редко большая проблема.Если вы действительно хотите буферизовать некоторые прошлые состояния на сервере, вы можете интерполировать между ними и отправлять разные старые данные разным людям в попытке синхронизировать то, что они видят, но в сочетании с имитацией на стороне клиента и дрожанием во время передачи, которое вы выполняете ».По-прежнему будут наблюдаться некоторые различия между машинами.

2 - типичный способ - запустить симуляцию на сервере и отправлять регулярные (небольшие) обновления состояния клиентам.Клиенты обычно запускают свои собственные симуляции и имеют возможность смешивать свое собственное прогнозируемое / интерполированное состояние с полномочным состоянием, которое сервер отправляет им.Все решения, кроме пользовательского ввода, должны приниматься на стороне сервера.В конечном счете, то, как вы смешиваете их, является просто компромиссом между гладким внешним видом и точным состоянием, поэтому вам придется принять косметическое решение.

3 - ваш клиент обычно должен переводить нажатие клавиши в логическое действие.Ваш сервер не заботится о ключах.Отправьте это логическое действие на сервер, и оно может передать его другим клиентам, если оно им потребуется.В общем, хотя вам здесь не нужно ничего делать - любое соответствующее изменение, вызванное действием, как правило, просто изменит состояние игры и, таким образом, будет отправлено при обычной трансляции этого состояния.

5 голосов
/ 01 июля 2010

Я не буду обращаться к вашим точкам напрямую, потому что другие ответы так хороши. Но я предлагаю изучить HTML5, WebSockets и Comet, которые обещают значительно улучшить производительность в реальном времени. Эти технологии позволяют вам иметь длительные HTTP-запросы, позволяя серверу передавать данные клиенту, а не клиенту, опрашивающему сервер. Это может существенно ускорить процесс.

Вот некоторые ресурсы, которые должны оказаться полезными:

1 голос
/ 23 мая 2011

Если вам нужен пример кода для изучения, есть многопользовательская онлайн-игра Понг , выполненная в ActionScript , со стороны сервера. физика, интерполированная клиентами.

Этот пример Pong построен на платформе Union , которая доступна бесплатно для 1000 одновременных клиентских подключений.

Union имеет клиентскую среду JavaScript, OrbiterMicro (клиент JavaScript) .

И вы можете написать свою серверную логику также в JavaScript, см. Создание комнатных модулей с помощью JavaScript .

(Полное раскрытие: я соучредитель Союза.)

1 голос
/ 02 июля 2010

Лучший способ - отслеживать все объекты только в одном месте, а именно на сервере.Каждый увидит информацию с серверов на один раз позже, чем это «на самом деле», и людям понадобится одно путешествие, чтобы зарегистрироваться на сервере.Там действительно нет никакого способа обойти это.Для некоторых приложений может быть практичным смоделировать ваше собственное движение сразу, не дожидаясь ответа сервера, но это, несомненно, приведет к кошмару с программированием времени, и люди, как правило, видят друг друга «отстающими».Обнаружение столкновений практически невозможно.

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

1 голос
/ 22 июня 2010
  1. Это очень сложно сделать, и я вижу много проблем с синхронизацией с «самым медленным». Можете ли вы ослабить это, чтобы клиенты могли «в конечном итоге быть последовательными»?

  2. Звучит хорошо.

  3. Я бы отправлял события короткого действия из внешнего интерфейса в бэкэнд, велел бэкенду изменить состояние игры и публиковать события изменения состояния игры обратно клиентам, уделяя большое внимание только отправке необходимых событий нужным подписчикам. В этот момент вы можете отказаться от любых событий, которые не соответствуют или кажутся ложными / хаки.

0 голосов
/ 23 августа 2013

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

Другой вопрос StackOverflow: Синхронизация движения в многопользовательской игре

0 голосов
/ 01 июля 2010

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

Обычно клиент прогнозирует, как идут дела в течение коротких периодов времени, а затем исправляется обновлением с сервера. Вы также можете применить коррекцию времени. Например, если сервер сообщает вам, что «игрок 2 находится на P, движущемся со скоростью V», вы можете попытаться узнать, сколько лет этому сообщению может быть основано на недавнем пинге, и скорректировать положение с P до P + x*D. .

...