Хранение шестигранной сетки

10

Я создал небольшую инфраструктуру с шестигранной сеткой для Unity3D и пришел к следующей дилемме. Это моя система координат (взято отсюда ):

введите описание изображения здесь

Все это работает довольно хорошо, за исключением того факта, что я понятия не имею, как его хранить. Первоначально я намеревался хранить это в 2D-массиве и использовать изображения для создания своих карт.

Одна проблема заключалась в том, что он имел отрицательные значения (это было легко исправить, немного сместив координаты).

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

Является ли написание набора переводчиков координат лучшим решением здесь?

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

PEEC
источник
1
Разве вы не можете просто сохранить изображения PNG, которые прозрачны вокруг шестиугольников?
Маркус фон Броади
Моя главная проблема с сохранением в png и массивах - это количество «пробелов», которое они должны были бы содержать, чтобы сохранить эту систему координат нетронутой.
PeeC
1
Если «пробел» означает прозрачные пиксели, то почему это проблема?
Маркус фон Броади
Это очень хороший момент. Большинство графических форматов не тратят столько памяти на хранение повторяющихся шаблонов. Но все - таки, это немного раздражает меня , что хранить эту карту , я использую это много памяти (серые пиксели пустого пространства, другие цветами являются действительными координатами шестигранной).
PeeC
1
О, вы храните данные сетки, а не мозаичные изображения! Почему вы не просто сохраните свои структуры данных (сетку) в двоичный файл или закодируете его, например, с помощью JSON, и сохраните в текстовом файле? Хотя я не знаю возможностей Unity. Кроме того, вы можете подтвердить это, но я считаю, что область того же цвета оптимизирована (слабо сжата) в формате PNG.
Маркус фон Броади

Ответы:

9

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

Наблюдение: в каждой строке карты данные сетки непрерывны. Все потраченное впустую пространство находится слева и справа.

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

Выполните преобразование в получателе и установщике для карты, с чем-то вроде этого:

inline function get(q, r) {
    first_column_in_this_row = -floor(q/2);
    return array[r][q - first_column_in_this_row];
}

Вы должны будете изменить это, чтобы работать с вашим выбором координат и карты (обратите внимание на одно отличие). В некоторых макетах вы хотите сместить столбцы по строке, а не наоборот.

Вы можете использовать тот же трюк для создания карт других форм; это не ограничено прямоугольниками.

Если вы используете C или C ++, вы можете использовать арифметику указателей, чтобы сделать это быстрее. Вместо того, чтобы хранить массив указателей на массивы, сохраняйте массив указателей, которые были изменены first_column_in_row. (Это не может быть портативным)

amitp
источник
Это работает, насколько я могу судить, однако математика была действительно странной. После опробования нескольких уравнений, которые имели смысл в моей голове, я остановился на yIndex = y-((x%2==0)?(x/2-x):(-x/2)-1)некоторых пробах и ошибках. Понятия не имею, как это работает жестко.
PeeC
Сделай это yIndex = y-((x%2==0)?(-x/2):(-x/2)-1). x / 2 - это все целочисленные значения между прочим, так что нет необходимости в полу.
PeeC
6

Лично я предпочел бы простоту экономии памяти. Не оптимизируйте, пока не понадобится!

Если вы все еще хотите сэкономить несколько байтов, вот как вы можете это сделать:

введите описание изображения здесь

  1. Разрежьте параллелограмм пополам, чтобы сформировать два прямоугольных треугольника.
  2. Переставьте два треугольника, чтобы сформировать прямоугольник.
  3. (Обратите внимание, я добавил зеленую буферную полосу, чтобы математика работала хорошо.)

Код Python для отображения координат прямоугольника на координаты параллелограмма и обратно:

# Height of rectangle
H = 15

def r2p(x, y):
"rectangle to parallelogram"
if y < -x/2 + H:
    y = y + H
return (x - 1, y)

def p2r(x,y):
"parallelogram to rectangle"
if y >= H:
    y = y - H
return (x + 1, y)
Leftium
источник
2
Вы также можете просто переместить пиксели вертикально вниз - на изображении, которое будетoffsetY = Math.floor ( (x+1)/2 )
Маркус фон Броади
1

Нет необходимости искажать карту, поскольку преобразование между прямоугольными и «каноническими» координатами происходит быстро и просто. Вот ссылка на введение о том, как это сделать:

Преобразование между прямоугольными и каноническими шестнадцатеричными координатами

Этот метод сочетает в себе ленивую оценку с кэшированием рассчитанных конверсий.

Питер Гиркенс
источник