гекс — основа многих боевых систем

Гекс (гексогон) – шестигранник.

В последних статьях, я много говорил о боевых полях и формировании боевых карт. Все примеры были построены на основе четырехугольных секторов – клеток.

Но значит ли это, что клетка лучше шестигранника? Попробуем разобраться.

Клетка – простая форма, имеющая четыре вершины и столько же сторон. Главный плюс: простота расчета, по сравнению с любой другой формой.

У шестигранника дела обстоят хуже, гекс имеет шесть вершин и шесть сторон.

Клетка и гекс - различия видны невооруженным взглядом.

Клетка и гекс — различия видны невооруженным взглядом.

Но есть одно не маловажное преимущество. Если рассмотреть поле клеточное, то присмотревшись, можно заметить, что не смотря, на то что, клетки «квадратные» стороны равны и вершины равноудалены, расстояние между смежными клетками разное. Не верите? А вот взгляните на схему:

Сравниваем поле из и клеток с полем из гексов, преимущества и недостатки очивидны.

Сравниваем поле из и клеток с полем из гексов, преимущества и недостатки очевидны.

Как видно, что клетки имеют не четыре, а восемь соседей. Четыре соседа имеют общую сторону с нашей клеткой, они отмечены желтым, а другая партия соседей, имеют общие вершины( эту команду я отметил красным). Да, соседи по вершинам не так очевидны, но тем не менее они есть.

Теперь достаточно сделать простые визуальные измерения линейкой, и мы видим следующее: расстояние между центрами «соседей по сторонам»  меньше расстояния «соседей по вершинам». Таким образом, мы сталкиваемся с весьма серьезной, хоть и малозаметной проблемой – расстояние между клетками не едино. Подобные проблемы вызывают много хлопот, когда в игре расстояние играет роль.

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

Основные правила построения поля из гексов.

К сожалению взять и просто нарисовать вместо клеток гексы не удастся. Алгоритм, выполняющий построение по клеткам, выдаст вам весьма неожиданный результат. По этому требуется перестроить «клеточный» алгоритм под использование шестигранников.

И так, клеточный алгоритм выглядит примерно так:

For (int x =0; x<8;x++)
{
                For(int y; y<8;y++)
{
                «Построить клетку»
}
}

Данный цикл строит по восемь клеток в каждом ряду, восемь раз.

Естественно, что в цикле задается смещение следующего ряда ровно на ширину клетки, что позволяет строить клетки «одна к одной».

В итоге мы получаем правильную структуру клеточного поля.

Для использования гексов, стоит учесть основные правила:

1. «Каждый новый ряд смещать на половину размера»

2. «Задавать направление смещение каждого нового ряда операясь на четность/ нечетность номера ряда».

Вот такие простые правила играют основную роль. Все остальное как и с клетками, нарисовал, сдвинулся, нарисовал.

Но хотелось бы подробнее остановиться на втором правиле.

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

Алгоритм построения поля основанного на гексах

Псевдокод алгоритма:
Float StartPositionX = 10; //Позиция, в которой строится первая клетка X
Float StartPositionY = 10;  //Позиция, в которой строится первая клетка Y
Float xStart= 1;
Float  yStart = 1;
Float Size = 1; // Размер клетки
Bool  chet = false; // Четность ряда
For (int x =0; x<8;x++)
{
      For(int y; y<8;y++)
{
If(chet)
{
«Построить клетку в позиции:
StartPositionX
StartPositionY + yStart» //Переменная chet является true значит ряд четный, необходимо смещение!
}
If(!chet)
 {
«Построить клетку в позиции:
StartPositionX
StartPositionY»// ряд нечетный, значит стартовая позиция ряда равна стартовому Y поля.
}
}
yStart = Size/2;
StartPositionX += Size/2;
chet!= chet;
}

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

Разбор алгоритма

У нас есть стартовая позиция, где появится первая клетка поля. От этой позиции в циклах, будут строиться все остальные клетки поля.

xStart и yStart это переменные смещения, они нам рассказывают, куда сместить стартовую позицию следующего ряда. По сути они избыточны, можно обойтись и без них, применив сразу в цикле формулу, как в этой строке: «StartPositionX += Size/2;»,  Но для наглядности я их оставил.

Стартует вложенный цикл и проверяет переменную Chot, если она ложна, значит ряд нечетный. В этом случае, создавать ряд он будет без смещения, так как первый ряд, от которого все строится тоже является нечетным.

Выполнив 8 проходов, внутренний цикл завершается, и передает управление внешнему. Как видно из кода, в этот момент происходит смена значения переменной Chet на противоположное значение, и наше нечетное, становится четным. Кроме того, происходит смещение StartPositionX += Size/2; Ряд смещается ровно на половину ширину сектора по X, что удовлетворяет правилу номер 1.

Но на этом еще не все. При втором проходе, цикл вновь запускает вложенного собрата, и вновь 8 секторов начинают строится, с одной лишь разницей – переменная Chet сменила значение, и значит выполняется противоположное условие, где Chet == true.

И если вы заметили, в этом варианте, к позиции по Y добавляется половина размера сектора! Этой простой манипуляцией нам удалось сдвинуть следующий ряд на половину размера, другими словами, мы выполнили правило номер 2, смогли проверить четность, и определили необходимое смещение.

Завершив построение второго (четного) ряда, программа вновь сменит значение переменной, отвечающей за четность, и третий ряд (нечетный) будет строиться по правилам нечетного построения. А смещение ряда по X происходит по обычным законам, с той лишь разницей, что вместо полной ширины, мы используем только ее половину.

Вот так просто и без особых хлопот нам удалось построить красивое поле из шестигранных полей. И поверьте мне на слово, если не хотите проверять, расстояние между смежными секторами одинаково, что уже само по себе является большим делом! Теперь то, даже по диагонали выпущенный снаряд, обязательно достигнет своей цели, а не разорвется в «полсекторе» до объекта.

[wysija_form id=»1″]

 

5 комментариев

  1. Сергей Гримс Сергей Гримс:

    Что-то в корабликах я не обнаружил гексов. Статейные преимущества на лицо, а применения нет.

  2. Bedndarc Bedndarc:

    «Кораблики» делались много раньше, чем была написана статья. Но, не это главное. В корабликах, боевая система не подразумевает точной дистанции для движения или атаки. Дистанция условна — 1 единица. А то что она +-0,7 в диагоналях, никак не сказывается на геймплее. Всему свое место — гексы к гексам, клетки к клеткам :)

  3. Сергей Гримс Сергей Гримс:

    Не соглашусь. Если верить написанному, то как раз ситуация с перекрыванием кораблей друг-друга, в моменты, «удачных разворотов» на близких точках, на мой взгляд из этой серии. Были бы гексы, возможно не было-бы перекрываний.

  4. Bedndarc Bedndarc:

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

  5. Автоматизирование позиционирование персонажа на боевом поле, с возможностью последующего расчета доступности конечной точки движения.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Проверка * Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.