Распознавание гексагональной кликбокса

17

Я работаю над игрой, в которой будут задыхаться шестиугольники.

В настоящее время у меня есть изображение шестиугольника, которое я использую (все стороны имеют одинаковую длину ... оно вписывается в изображение размером 50 на 50 пикселей).

Я немного новичок в C # и действительно новичок в XNA, но есть ли какой-то простой метод, который я могу вызвать, вместо того, чтобы делать сложный оператор if, основанный на точках и углах?

the_e
источник
См. Gamedev.stackexchange.com/questions/6382/…, в котором реализовано обнаружение шестнадцатеричных кликов.
Тим Холт
4
Я полностью гуглил "задыхающиеся шестиугольники", я был похож, "что это за шестиугольник ?!" Думаю, у меня медленный день.
MichaelHouse
2
Хм, что произойдет, если вы нажмете на вздох, а не на шестиугольник?
Тим Холт
1
В зависимости от ваших потребностей, простой круг подойдет, если только для области щелчка. В противном случае вам придется использовать точку на технике многоугольника, такую ​​как сумма сумм или сумма.
PhilCK
Если гекс-карта не должна быть произвольно повернута, точка на многоугольнике является ОГРОМНЫМ излишним. Что вы делаете с картой размером 1000x1000 гексов? Проверять каждого? RE: Круги, они не будут работать. Около вершины соединения между тремя гексами у вас будет три перекрывающихся круга. Меньшие круги, которые полностью лежат в гексах, будут иметь промежутки, в которых законные щелчки не будут ни в одном круге.
Тим Холт

Ответы:

18

Шестиугольник - это прямоугольник с обрезанными углами. То, как я это сделал, и я слышал, что серия Civilization делает это с помощью ортогональных карт, - это создание растрового изображения с пробелом (ортогональным или шестиугольным) и красным, зеленым, синим и желтым угол. (Или любые цвета, которые вам нравятся.)

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

Ортогональные: введите описание изображения здесь

Затем просто определите, на каком прямоугольнике находится курсор, и проверьте цвет пикселя в этом месте. Если он белый, они парят над этим пространством. Каждый другой цвет сопоставляется со смещением, и вместо этого они парят над этим шестиугольником. Этот способ эффективен, требует мало геометрии и может использоваться для любого произвольного тесселяционного пространства.

dlras2
источник
Только примечание: у шестиугольника есть 6 равных длин сторон. Ни одно из представленных вами изображений на самом деле не содержит шестиугольников. Вместо этого они содержат 6 односторонних многоугольников. Помимо этого, этот метод работает. Это, вероятно, медленнее, чем вычисление границ шестиугольника, для больших шестиугольников, так как этот метод требует больше места для больших шестиугольников (если вы хотите сохранить точность на пиксель). Для небольших шестиугольников (и в зависимости от аппаратного обеспечения) этот метод, вероятно, быстрее, чем вычисление границ.
Ольховский
9
Шестиугольник - это любой 6-сторонний многоугольник. То, о чем вы думаете, это равносторонний шестиугольник (на самом деле, вы, вероятно, думаете о правильном шестиугольнике, который является типом равностороннего и равностороннего шестиугольника)
Random832
Обратите внимание, что я не говорил, что ваш ответ был плохим. Я думаю, что это хороший ответ и решение, которое имеет место. Тем не менее, я бы не выбрал этот метод для вычисления границ шестиугольника, как для вычисления границ шестиугольника на любой современной платформе, так как вычисление границ является гораздо более расширяемым способом сделать это. Например, допустим, вы хотите изменить размер шестиугольника - теперь вам нужно перестроить изображение? Создание идеальной пиксельной шестиугольной маски - это боль. Я думаю, что тот факт, что вы его здесь не произвели, свидетельствует об этом.
Ольховский
2
@ Ольховский - я не создал здесь идеальную шестиугольную маску, потому что я отвечаю на вопросы как общественная работа во время моих нескольких минутных перерывов на работе, а не пишу видеоигру. ОП искал решение с меньшим количеством математики, и я подумал, что это было аккуратно, поэтому я решил поделиться, потому что это то, о чем я, конечно , не подумал бы самостоятельно.
dlras2
18

Там нет метода XNA, который делает проверку удара шестиугольника.

Эта статья объясняет, как написать функцию, которая выполняет тест, и дает вам функцию:

Как проверить, находится ли точка внутри шестиугольника

Вот краткое изложение этой статьи: шестигранный щелчок

И функция, выполняющая тест, выглядит так:

  1. Проверьте ограничивающую рамку вокруг шестиугольника, заблаговременно, если он не пересекает его.
  2. Преобразуйте точку в локальный квадрант, как показано выше.
  3. Выполните следующий isInsideтест для локального квадранта.

public function isInside(pos:Vec2Const):Boolean
{
    const q2x:Number = Math.abs(pos.x - _center.x);       
    const q2y:Number = Math.abs(pos.y - _center.y);
    if (q2x > _hori || q2y > _vert*2) 
        return false;
    return 2 * _vert * _hori - _vert * q2x - _hori * q2y >= 0;
}

Смотрите статью для более подробной информации.


Вот некоторые другие полезные связанные источники:

Ольховский
источник
1

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

public bool PointInPolygon( Vector2 p, Vector2[] poly )
    {
        Vector2 p1, p2;
        bool inside = false;

        if( poly.Length < 3 )
        {
            return inside;
        }

        Vector2 oldPoint = new Vector2( poly[poly.Length - 1].X, poly[poly.Length - 1].Y );

        for( int i = 0; i < poly.Length; i++ )
        {
            Vector2 newPoint = new Vector2( poly[i].X, poly[i].Y );

            if( newPoint.X > oldPoint.X )
            {
                p1 = oldPoint;
                p2 = newPoint;
            }
            else
            {
                p1 = newPoint;
                p2 = oldPoint;
            }

            if( ( newPoint.X < p.X ) == ( p.X <= oldPoint.X )
                && ( (long)p.Y - (long)p1.Y ) * (long)( p2.X - p1.X )
                 < ( (long)p2.Y - (long)p1.Y ) * (long)( p.X - p1.X ) )
            {
                inside = !inside;
            }

            oldPoint = newPoint;
        }

        return inside;
    }

Вам нужно дать углы вашего шестиугольника в массиве vector2 (poly) и нажатую позицию (p) для метода.

chr1s1202
источник