Сегодня я сделал для игры мини-карту. Рассказываю, что да как.
Так как вся работа идёт на движке Godot, у меня было много вариантов для реализации мини-карты. Это и дополнительная камера, смотрящая на карту сверху, и разного плана проекции, но, так или иначе, все они затрагивают камеру и влияют на производительность лишними рендерами.
Пришлось идти по другому пути, который более сложный в реализации, но во время игрового процесса не съедает FPS и позволяет играть без двойного рендера и лишних расчётов. Но пришлось потрудиться.
Шаг 1. Рендер каждой 3D карты отдельно
Так как все сцены у меня в 3D, модели есть в блендере, откуда их можно легко достать в виде 2D картинки. Для обработки использую GIMP, так что на каждую сцену на скриншот + обработка уходило где-то по 4 минуты
Игра немного пикселизованная, поэтому после скриншота качество ещё немного убавил.
В результате на каждую сцену получлся 2D аналог.
Шаг 2. Соотношение 3D карты и 2D карты
Тут всё сложнее. Каждая карта в 3D пространстве изначально не была расположена по какой-либо сетке, не имеет четкого "центра" и у всех карт разные размеры. Я долго думал, как лучше сделать, да ещё, желательно, универсально, чтобы не затратить кучу времени на это.
И решение пришло.
Тут всё, на самом деле, до банального, просто. Черная область на карте - это прямоугольник, обозначающий рамку относительно 3D карды для позиционирования в 2D.
Более наглядно.
Я думаю, вы уже понимаете, как дальше быстро и легко спозиционировать все карты. Просто располагаю черную область так, чтобы карта внутри неё соответствовала расположению карты на 2D скриншоте.
Шаг 3. Координаты и... координаты
При нахождении чего-либо на основной карте, мини-карта должна правильно понимать, где это находится в её локальных координатах.
Первой задачей стояло реализовать курсор на мини-карте, чтобы игрок понимал, где он находится и сколько вокруг него ещё пространства
Для этого мне нужны координаты по осям X и Z из большой карты, чтобы перевести их в X и Y в мини-карту.
Формула расчета координат несложная, но с некоторыми нюансами.
Первый из нюансов, начало координат в 2D сцене - 0,0 по осям X,Y, начало в 3D сцене всегда разное, то есть та черная область может иметь любые координаты по осям X,Z, и они никак не фиксированы. Этот фактор является смещением начальных координат.
Соответственно, чтобы учитывать позицию объекта в 3D сцене нужно от неё отнимать точку начала координат.
После этого нужно взять размеры области в 3D, поделить ей на размеры мини-карты в 2D, и разделить позицию в 3D на получившееся значение.
В псевдо-кодах это выглядит так:
функция проекция3Dв2D(позиция3D) {
позиция3D -= началоКоординат3D // тут сразу и X и Y
позиция2D.X = позиция3D.X / (область3D.ШИРИНА / область2D.ШИРИНА) - смещение
позиция2D.Y = позиция3D.Y / (область3D.ВЫСОТА / область2D.ВЫСОТА) - смещение
вернуть позиция2D
}
В результате функция нам возвращает правильные координаты на 2D карте любого 3D объекта.
Шаг 4. Корректировки
Если вы заметили, в формуле участвует параметр "смещение".
Смещение - это небольшая корректировка объектов на 2D плоскости, с учетом размеров маркера, дабы центр маркера и центр объекта совпадали. Смещение нужно, так как отсчёт в 2D, как правило, идёт не от центра, а от левого верхнего угла.
Так же помимо этих корректировок, при взятии позиции объектов учитывается небольшое смещение камеры, так как она под наклоном, и её фактическая позиция не соответствует той, где находится область перекрестия.
Итог
В итоге всё получилось, карта полностью рабочая, и на неё можно располагать любые маркеры любых размеров и позиций. Из статьи я выкинул все неинтересное, и надеюсь, она будет кому-то полезна.
Всем большое спасибо за внимание!
Так же, мои статьи выходят и на DTF