Подгружаемая карта в игре с несколькими точками загрузки, как избежать коллизий и объединить соседние элементы

Карта лежит в базе данных, достается она оттуда кусками 16х16(Chunk).

Есть статичный класс карты Map.

В текущий момент в игре реализован загрузчик чанков ChunkLoader. Он отправляет Map координаты объекта, около которого нужно прогрузить карту определенного радиуса(для простоты возьмем 3х3).

Загруженные Chunk'и сохраняются в четырехсвязный список QuadList(ну или графы, принцип тот же: ссылки на соседние элементы). Выбрана данная структура из-за удобства добавления и удаления элементов по краям. Хранятся в оперативной памяти только ссылки на крайние элементы(4шт, по углам).

Вроде бы все работает хорошо, но вот возникает проблема: при добавлении еще одного ChunkLoader'а прогруженные Chunk'и могут начать пересекаться, следовательно Map будет отрисовывать одни и те же куски, если иметь отдельный QuadList на каждый ChunkLoader. Но это не так страшно, хуже всего то, что непонятно как реализовывать теперь логику перемещения объекта, поиск пути.

Вопрос состоит в том: как модифицировать текущую структуру хранения прогруженной карты, чтобы исключить коллизии одинаковых Chunk'ов? И сделать возможным следующее: соседние Chunk'и должны быть связаны независимо от объекта, ChunkLoader которого вызвал прогрузку этих Chunk'ов. Если они не пересекаются и не граничат, то соответственно никак не связаны.


Ответы (1 шт):

Автор решения: Yaroslav

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

Из чего следует, что должен быть менеджер лоудеров организующий взаимодействие, коим может быть Map или нет. Алгоритм спавна чанка у лоудер:

  • 1) void RollChankFromSpawn() лоудер выбирает от какова чанка спавнить (скажем чанк с координатой 9х7)
  • 2) выбирает кондидата из пустых координат по соседству (пускай 10х7)
  • 3) void PrepareSpawnOnTile(Vector2 tile, bool checkEmpty) собирает инфу о соседних, о 9х7 уже знаем, но в чанке могут храниться и другие (допусти ещё 10х6)
  • 4) ещё 2 "пустых" (11х7 и 10х8) которые могут быть частью других чанкоч, поэтому спрашиваем у менеджера лоудеров ChunkLoader HasChunkOnTile(Vector2 pos) выдай лоудер с чанком по этой координате для обоих.
  • 5a) если оба ответа от менеджера null, то void SpawnChunkOnTile(Vector2 tile).
  • 5b) если нет, говорим менеджеру объединить лоудеры void ConnectLoadersAndSpawnChunkOnTile(ChunkLoader[] loaders, Vector2 tile). В массиве сам лоудер который хотел спавнить и остальные не повторяющиеся лоудеры, оказавшиеся в "пустых" позициях (может получиться до 4) и куда мы будем спавнить сразу с пункта 3) без 4) после обьединения (поглащения одним лоудером, списков чанков и QuadList'ов остальных). Заодно решит проблему поиска путей.
→ Ссылка