Недавно возникла дискуссия о том, как создать многопользовательскую многопользовательскую игру с боковой прокруткой, которая может иметь дизайн с зацикливанием уровней (подумайте о Starbound и о том, как зацикливаются их миры).
Я подумал, что самым простым способом было бы иметь прямоугольную карту с триггерными зонами, которые могли бы телепортировать игроков с одной стороны на другую. Однако очевидной проблемой этого подхода является случай, когда несколько игроков находятся на краю карты одновременно. Вы не хотите просто телепортировать игроков друг против друга, и вам нужен способ транспортировки игроков без исчезновения других игроков.
Чтобы добавить эту идею и исправить проблему, я придумал следующее: иметь триггерную зону (красный квадрат на изображении), где игроки смогут увидеть «зону клона» (зеленый квадрат). В этом зеленом квадрате объекты с противоположной стороны триггерной зоны будут скопированы в соответствующую зону клонирования (это можно увидеть с помощью фигур A & B). Когда игрок достигает начальной границы «зоны клонирования», он телепортируется на другую сторону карты.
В этом примере игрок 2 подумает, что он видит игрока 1, однако на самом деле он увидит его клона и наоборот.
Это казалось немного экстремальным и сложным для рассматриваемой проблемы. Мой вопрос теперь состоит в том, чтобы знать, является ли это решение хорошим подходом к решению проблемы, или есть более простой способ решить эту проблему?
источник
Ответы:
Эта система со всеми этими триггерами звучит слишком сложно и подвержена ошибкам.
Вы можете обернуть позицию игрока, используя по модулю что-то вроде
playerPositionX = playerPositionX % mapWidth
Таким образом , когда ваш игрок достигает сбрасывается обратно в 0.
playerPosition == mapWidth
playerPosition
Это решение может быть расширено всей системой рендеринга.
источник
pos - map_width
).Каноническим решением является использование порталов . В вашем примере есть только один уровень, за исключением того, что есть портал, соединяющий левый и правый концы.
Все, что движется по этому порталу, получит свои координаты, переведенные на другой конец портала, так что если что-то движется влево через портал, оно появится снова на правой стороне уровня и наоборот.
Ваша камера также должна поддерживать порталы; если портал находится внутри камеры, то он должен отображать части уровня по обе стороны портала. Если вы знакомы с графическими редакторами для бесшовной графической мозаики, то здесь то же самое.
Утомительная часть заключается в том, что все, что касается расстояния или пути, также должно поддерживать порталы. Это включает ИИ, алгоритмы прямой видимости, затухание звука и так далее.
Хорошая особенность порталов в том, что они очень мощные. Движок сборки использовал его для имитации многоуровневых уровней, несмотря на то, что он не был «настоящим» трехмерным движком. Некоторые современные движки тоже используют порталы для создания неевклидовых пространств; Portal и Antichamber являются яркими примерами в 3D.
источник
Помните, что то, что вы отображаете на экране, и то, что находится в памяти, - это две совершенно разные вещи. Представьте, что у вас есть окно, которое вам нужно заполнить данными о мире. Вы заполняете окно слева направо. Пока вы анализируете свои данные, чтобы заполнить мир, если вы достигнете конца света, просто вернитесь к началу ваших данных. Использование операции по модулю идеально. Помните, что вы должны сделать это для всего . Снаряды, лучи, игроки, физика; им всем нужно обернуть свои позиции при пересечении границ мира.
Каждый игрок делится данными, но имеет свою точку зрения на данные. Их окна заполнены по-разному в зависимости от того, где они стоят в мире.
Это означает, что нет необходимости создавать клонов или телепортировать кого-либо. По сути вы являетесь создание клонов, просто визуализаций символов на экраны друг друга.
источник
Отключите рендеринг от мира, и вы сможете сделать обход и исправить рендеринг, не прибегая к каким-либо артефактам клонирования или телепортации.
Во-первых, в вашем мире у вас есть мир фиксированного размера, от
0
доWidth
. Каждый раз, когда объект опускается ниже 0, вы оборачиваете его до конца, а каждый раз, когда объектWidth
перезагружает его до начала. Это означает, что все логические объекты в вашем мире всегда находятся в пределах досягаемости0...Width
.Во-вторых, для рендеринга вы будете делать по модулю позицию. Таким образом, левая сторона экрана - «База», а правая - «База + Размер». Итак, вы просматриваете свой мир на предмет чего-либо в этом диапазоне. Вы на самом деле будете искать диапазон по модулю, который отобразит его обратно
0...Width
.Хитрость при поиске состоит в том, чтобы вернуть положение объекта относительно
Base
левой стороны. Это преобразует в локальные координаты экрана, так что самому рендереру не нужно беспокоиться о модуле, только поиск.Вам не нужно ничего клонировать, поскольку каждый рендерер имеет дело только с объектом в одном месте.
Если ваш мир создается сегментами или с использованием трехмерных структур, вам придется сегментировать его. Таким образом, это не один случайный блок, но его можно переместить, чтобы приспособить этот рендеринг. Вам не нужно много блоков, как минимум 2.
источник
Я думаю, что единственным разумным подходом было бы реализовать ваш окружающий мир в базовой структуре данных, полностью прозрачной для игры и пользователя. Так что на каком-то низкоуровневом уровне у вас есть функция mapCoordinate (), которая оборачивает ваши фактические координаты в базовый ресурс карты ...
Таким образом, если ваш настоящий Мир имеет ширину всего 10 единиц, игрок и игра не узнают об этом. Для игрока мир бесконечен - и если игра спросит, что находится в позиции 15 - основная функция переведет этот запрос по модулю10 и даст упаковать предмет в позицию 5.
Таким образом, для всей игровой логики и всего остального это так же, как если бы у вас был бесконечный большой мир, где просто бывают копии всего.
источник
Это не совсем то же самое, но я реализовал нечто подобное в игровом джеме. В игре игроки двигались по маленькому круговому уровню, оборачиваясь, когда игрок достигал позиции «х» числа «пи». Рендеринг был легким, потому что мы просто рендерили все, а затем вращали смещенную камеру, чтобы отслеживать происходящее. Вы можете реализовать нечто подобное, как было предложено выше:
источник