Подтвердить что ты не робот

Многопользовательская игра с бэкэндом и интерфейсом JavaScript. Каковы наилучшие методы?

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

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

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

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

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

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


EDIT: они полезны:

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

  • Звучит неплохо.

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

Ответ 4

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

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

Ответ 5

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

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

У Союза есть клиентская среда JavaScript, OrbiterMicro (клиент JavaScript).

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

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

Ответ 6

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

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

Ответ 7

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

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