Pull to refresh

Comments 75

Если не секрет, то можете показать примерный код работы сервера?
Вообще, там очень немаленький репозиторий на golang. Открывать код мы не планируем.

Что-то не так у вас с физикой — инерции не хватает.

Игрушка казуальная. Так и задумано.

Не надо путать казуалов и даунов.

Странная логика. Angry birds и Cut the rope, например, тоже казуальные игры, но с физикой там все в порядке.

Скорее поленились разбираться или ресурсов нет.
Отскоки с одной скоростью и отсутствием контроля — ну сразу обламывает кайф игры.
starblast.io вполе себе с физикой.


А за статью спасибо.

Поменяли физику. Как вам сейчас?

Стало лучше, хотя мышкой всё-равно тяжко управлять. Удобнее было бы с клавы.

Поменяйте сертификат на Letsencrypt — вас ждет сюрприз с Chrome Beta (который скорее всего выйдет из беты в середине марта)

Ну как в середине марта, версия под мак "Version 56.0.2924.87" уже не открывает.


Я что-то пропустил, но с каких пор хром не разрешает зайти на сайт даже если мне очень хочется, забив на сертификат? Раньше было под «advanced»
Вы правы. Перед официальным релизом обязательно так сделаем.

Можете подсказать, что не так случится с letsencrypt? Использую его везде, первый раз слышу, что что-то с марта поменяется.

Хмм, да, звучит двусмысленно. Начиная с Chrome 57 сертификаты от Startcom и WoSign окончательно превращаются в тыкву. А Letsencrypt планирует жить и здравствовать

Спасибо, сняли камень с моей души) мигрировать была бы боль

Поменяли. Только не на letsencrypt а пока на comodo. Так быстрее было.
Если бы мне сказали реализовать управление в игре космическими кораблями на плохом канале (с плохим пингом), я бы вообще не использовал координаты (положение), разве только как средство дополнительной синхронизации.

Используем законы физики: тело, на которое не действует никакая сила, продолжает движение прямолинейно. F = ma, масса корабля либо фиксированная, либо уменьшается (если кто-то в игре реализует топливо, либо меняется, если кто-то в игре реализует релятивистскую физику), в простейшем случае — не меняется. В силу того, что даже ускорение нельзя менять мгновенно, мы просто передаём с клиента его текущее значение ускорения, задержки между передачами ускорения соответствуют «инерции педали».

Раз в N времени пользователь может поменять значение вектора ускорения (или значение скаляров ускорения и угла поворота рулей). Дальше чистая физика.
В принципе, так все и есть. Только один момент — что вы предлагаете делать, если из-за задержки пакета с измененным ускорением, кораблик на клиенте продолжил лететь с прежним ускорением дольше, чем было надо?
Ошибки будут накапливаться. (Я пробовал так — правда будут)
«Педаль реагирует с задержкой» — и всё.

Да, я забыл сказать, что в ответ сервер присылает не «реакцию» на нажатие педали, а timestamps (в общем frame of reference) моментов изменения ускорения всех объектов. Имея трансляцию из frame of reference в локальное время, клиент может полностью воспроизвести изменение скоростей и просчитать траекторию. Т.к. ошибки округления накапливаются, иногда сервер присылает уточнённые абсолютные координаты объектов.

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

Задача перевода одной гладкой функции в другую реализуется очень просто — используем экстраполяцию идеальной тракетории на следующую точку, а потом интерполируем точки ошибочной тракетории плюс одна (две?) точки, экстраполированные из идеальной траектории. Дальше по заданной тракетории мы можем посчитать производную третьего порядка в нужных нам точках для определения изменения ускорения (что соответствует визуальному «подруливанию») корабля.
Да, теперь практически все совпало ( с точностью до используемой физики). Единственный скользкий момент здесь — синхронизация часов сервера ии клиента. Небольшое расхождение даст неприятный эффект.
Синхронизаций есть два вида: соответствие t0 на сервере и на клиенте (реализуется элементарно, достаточно запомнить смещение для первого пакета), и расхождение Δt через некоторое время. Вторым можно пренебречь.

Ключевым моментом является сохранение плавности — то есть отсутствие разрывов в третьей производной. По бедности — во второй, хотя будет ощущение неестественных рывков.
> достаточно запомнить смещение для первого пакета
Не достаточно. Они не настолько равномерно ходят. Задача решаема, (например, так). Но несколько громоздко для игрушки.

Но в целом, все, что вы говорите, правильно. Хотя и немного переусложнено, для наших целей.
Это уже и так освещалось подробнее тут. Без технических подробностей бесполезная статья. Хоть бы куски кода, какой сервер, где и прочее.
На мой вгляд, описание работающего пртокола, на создание которого было потрачено немало времени и услий — вещь небесполезная.
А в чем проблема просто держать на клиентах технические характеристики всех кораблей (скорость движения, ускорение, и так далее), и положения курсоров всех противников? Что бы, по сути, клиент и сервер просчитывали движения всех кораблей самостоятельно и одинаково?

Да, есть 2 проблемы на первый взгляд:
1) рассинхронизация таки будет иногда, но можно, скажем, делать легкую синхронизацию постоянно (к примеру, хешировать состояние, и сравнивать хеши), и если есть рассинхрон, тогда заказывать полный снепшот с сервера
2) читеры. Но, я думаю, и так будущее положение корабля может дать преимущество

Есть еще тема. Каждое действие игрока сразу отправляется на сервер, где попадает в общий лог действий игроков с временными метками. Каждый клиент получает такой же лог, как и все остальные. Имея ТТХ кораблей и лог, все клиенты будут отрисовывать игровое поле абсолютно идентично и без рассинхронизаций в принципе. Даже события типа «ранил», «убил» будут генерироваться самостоятельно и идентично на всех клиентах. Минус — если игрок двинул мышью, то его локальная копия игры отреагирует только, когда получит ответ от сервера с временной меткой
Проблема в том, что время (абсолютное) на сервере и на клиенте может не совпадать. И сделать его идеально одинаковым не получается.
этого и не нужно. Временная метка все равно проставляется исключительно сервером. Клиент берет ее за основу даже для своих событий (сам двинул мышкой).

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

Судя по всему так сделали Blizzard в Heroes of the Storm. Реконнекта приходится ждать по 5-7 минут пока клиент просчитает все что происходило за период дисконнект-соединение.

В чем проблема синхронизирваться с сервером с учетом пинга и использовать абсолютное или лучше относительное время с периодическим пересчетом?
Можно, но сложновато. Не в том смысле, что лень делать. А в том, что каждый новый уровень сложности добавляет в систему хрупкости. Если можно не усложнять, нужно не усложнять.
было интересно почитать, но играть в это Г невозможно
Почему? (правда интересно)
ohm ответил мне в личку. Вопрос снимаю. Спасибо за полезный фидбэк!
Молодцы, граблей собрали :)
Насчет физики, мой вариант сильно приятнее: space.playcode.io

Кстати я тоже на Go пишу и интересна тема agar.io like игр.
Напишите мне (в профиле есть контакты).

Да, приятнее управление, чем у ТС, но что будет при взаимодействии с массой других игроков.

Очень интересно.
И использованный на бекенде язык тоже )
Сделали поближе к вашему варианту. Спасибо!
У нас получается работать удаленно :)
было интересно последить за ходом вашей мысли :)
Хотел показать, как простая, на первый взгляд, задача не всегда решается сходу.
А простое решение часто создается не самым простым способом.

Интересно было бы реализовать p2p коммуникацию. Допустим каждый посылает каждому свои координаты на следующую долю секунды. Каждый узел рассчитывает всю физику и рассылает результат пирам. Если показания расходятся (читер подделывает показания), то сеть автоматически распадается на непротиворечивые подсети. Таким образом читер будет играть сам с собой, а нормальные игроки друг с другом. Соответственно кластеров может быть сколько угодно, совершенно не нагружая сервер.

С чисто исследовательской точки зрения, соглашусь. Интересно. Но с практической — ненужная трата ресурсов.

Каких ресурсов? Наоборот, на сервере почти не тратим ресурсов, а клиентам так и так считать физику приходится для плавности движений.

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

Стоит FF последней версии, открыто 2 вкладки habr и сайт игры — тормоза страшные, корабли рывками прыгают и «телепортируются», даже меню выезжает с дерганьем. Через 30 сек FF выдал такое:

An error occurred running the Unity content on this page. See your browser's JavaScript console for more info. The error was:
NS_ERROR_NOT_CONNECTED:

В консоли:
An abnormal situation has occurred: the PlayerLoop internal function has been called recursively. Please contact Customer Support with a sample project so that we can reproduce the problem and troubleshoot it.

(Filename: Line: 56)
Спасибо. Такой баг был в одной из прошлых версий юнити. Вроде его исправили. Но, похоже, снова появился. Он повторяется при перезапуске браузера?
Попробую собрать клиент последней версией юнити. Возможно, поможет.
Ошибка за пару минут игры не появилась, но тормоза остались те же, даже с отключенной музыкой, звуками и низкой графикой установленными в настройках. Попробовал запустить на хроме (но он уже на WinXp давно не обновлялся), то же самое — тормозит всё неимоверно. Вообще странно конечно… не знаю, может проблема с соединением к вашему серверу, коннект за пару минут 1 раз отваливался.
А FPS Какой показывает (слева вверху)?
Когда меню выезжает 3-5, в процессе игры 7-15
Значит просто не тянет железо. В норме должно быть 60. Минимум 45.
WebGL штука прожорливая

Можно физически уменьшить окно браузера — это помогает видеокарте.

Можно зайти в настройки и повыключать все что можно (фон, вращение, качество моделей)
Но играть на таких настройках грустно.
Куда мир катится… :)

Devil May Cry 4, Need for Speed: Most Wanted… работает без тормозов, а простенькую леталку на минимальных параметрах не тянет GeForce 630 и Athlon 64 3200+ 2.1Гц… вот он прогресс 2004 — 2017 и хвалебные песни «быстрой разработке».

P.S. при уменьшении окна браузера действительно +5 fps
Это так. WebGL — вообще сыроватая технология. Ожидается, что там будет прирост производителеьности еще довольно большой.

Кстати, если у вас комп с двумя видеокартами, то браузер всегда использует ту, что послабее.
WebGL — всего-лишь js-обертка над OGL ES. Расскажите поподробнее что именно в ней сырое? И, если не сложно, расскажите за счет чего ожидается большой прирост производительности, можно даже просто ссылкой на пруф.
Тут немного шире проблема. Я был неточен.
Сам js на котором написана логика клиента — медленный и к тому ж однопоточный. Первый шаг в сторону его ускорения — asm.js Именно его использует Unity и, соответственно, эта игра.
Дальше ждем webassembly а также поддержку многопоточности.
Ну и работает пока нормально только webgl 1.0 (который обертка над opengl 2).
Кроме того, реализация поддержки его браузерами пока не идеальна и улучшается почти с каждой версией.
Достаточно же просто иметь на клиенте данные, которые нужны для расчёта будущих движений в предположении бездействия игроков. Исходя из этого можно постоянно иметь свою версию происходящего на клиенте и получать в дополнение к ней версию сервера с небольшой задержкой. Ну и плавно подправлять траектории в случае расхождения. В том же agar.io достаточно хранить направление движения каждого объекта. Там, правда, будут проблемы с поглощением объектов, так как непонятно, что делать, если в версии клиента оно произошло, а в версии сервера – нет. Ну или наоборот.
Мы ровно это и сделали в итоге.
Решил поиграться, через несколько минут увидел следующее:

У Вас закончились все жизни!
Одна жизнь восстановится через 28м.26c.
Либо, Вы можете купить жизни или дроида: (далее контент донат-магазина)

Вы, что, серьезно???

Я смотрю, у вас маркетологи ушли не на много дальше программистов ))
Речь идет о внтуриигровой валюте.
Ну да, речь про игровую валюту, покупаемую в том числе (читай, в основном) за реальные деньги.

Ограничение игры по времени, продлеваемое за валюту — суть подписка.

Вы, естественно, считаете, что на вашу игру люди будут с удовольствием подписываться плюс арендовать (вы что, серьезно???) явно выраженные игровые преимущества, но меня не покидает чувство, что ваша бизнес-модель потерпит фиаско.
Тонкость в том, что поступающего из игры потока внутриигровой валюты должно хватать абсолютному большинству игроков. Статистика по нашим другим играм: 99% игроков играют бесплатно. 1% настоящих фанатов игры делают всю кассу.
Тогда тем более уберите эти ограничения времени. Ведь, я уверен, большую часть дохода приносит продажа шмота, а не продажа жизней. Это очень легко объясняется — люди покупают шмот чтобы нагибать, а не для того, чтобы погибать. Зато уровень лояльности ваших игроков заметно повысится и не исключено, у вас станет 2% настоящих фанатов ))
Не исключено, что вы правы. Балансом в этой игре мы еще всерьез не занимались. Релиза не было.

Почти все статьи на хабре про "как мы писали сетевую игру" проходит через одни и те же стадии :)

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

Почему вы не увидели в моей статье описание протокола, мне непонятно. Вот же оно:
  • клиент отсылает на сервер положение мыши раз в 120мс
  • получив эту управляющую команду, сервер пересчитывает координаты корабля
  • асинхронно, на сервере работает нитка, которая ровно один раз в те же 120мс отправляет на клиенты координаты, в которых корабль должен быть к концу следующих 120мс
  • получив координаты, клиенты делают простой расчет: если сейчас кораблик находится в точке А, то с какой скоростью надо передвигать его в течение следующих 120мс, чтобы он оказался в пришедшей с сервера точке B


На сегодня 111 человек сохранили статью в избранное, что говорит о некоторой её полезности.

Насчет ссылки — тут дилемма. Поставь — вы упрекнете в рекламе. Не поставь — спросите: «Где пруфы, Билли?»
Вот же оно:

При всём уважении, это не протокол.

Этого достаточно, чтобы реализовать работающую вещь, особо не задумываясь и не набивая шишек.
Вам стоит прогуглить слова «протокол» и «алгоритм», дабы не путать эти два понятия.
Протокол передачи данных — стандарт, описывающий правила взаимодействия функциональных блоков при передаче данных.
Sign up to leave a comment.

Articles