Reconhecendo uma caixa de clique hexagonal

17

Estou trabalhando em um jogo que envolverá hexágonos de suspiro .

No momento, tenho uma imagem hexagonal que estou usando (todos os lados têm o mesmo comprimento ... cabe em uma imagem de 50 por 50 pixels).

Eu sou um pouco novo em C # e realmente novo em XNA, mas existe algum tipo de método fácil que posso chamar em vez de fazer uma declaração if complicada com base em pontos e ângulos?

te
fonte
Consulte gamedev.stackexchange.com/questions/6382/…, que implementa a detecção de clique hexadecimal.
Tim Holt
4
Eu pesquisei totalmente "hexágonos ofegantes" no Google: "que tipo de hexágono é esse ?!" Acho que estou tendo um dia lento.
MichaelHouse
2
Hmm, o que acontece se você clicar no suspiro e não no hexágono?
Tim Holt
1
Dependendo das suas necessidades, um círculo simples seria suficiente apenas para uma área de clique. Caso contrário, você terá que usar um ponto na técnica de polígono, como soma ou soma de enrolamento.
PhilCK 22/07
A menos que o mapa hexadecimal seja rotacionado arbitrariamente, o ponto no polígono é um exagero MAIOR. O que você faz com um mapa com 1000 x 1000 hexadecimais? Verifique cada um? RE: Círculos, eles não funcionarão. Perto do vértice da junção entre três hexágonos, você terá três círculos sobrepostos. Círculos menores que ficam completamente dentro dos hexágonos terão espaços onde os cliques legítimos não estarão em nenhum círculo.
Tim Holt

Respostas:

18

Um hexágono é um retângulo com cantos cortados. A maneira como eu vi isso e ouvi a série Civilization fazer dessa maneira com mapas ortogonais é criar um bitmap com um espaço em branco (ortogonal ou hexagonal) e um vermelho, verde, azul e amarelo canto. (Ou as cores que você preferir.)

Hexagonal: Máscara hexagonalouinsira a descrição da imagem aqui

Ortogonal: insira a descrição da imagem aqui

Em seguida, determine qual retângulo está o cursor e teste a cor do pixel nesse local. Se é branco, eles estão pairando sobre esse espaço. As outras cores são mapeadas para um deslocamento e, em vez disso, passam o mouse sobre esse hexágono. Dessa forma, é eficiente, requer pouca geometria e pode ser usado para qualquer espaço arbitrário em mosaico.

dlras2
fonte
Apenas uma observação: um hexágono tem 6 lados de comprimento igual. Nenhuma das imagens que você apresentou realmente contém hexágonos. Em vez disso, eles contêm polígonos de 6 lados. Fora isso, esse método funciona. É provavelmente mais lento do que calcular os limites do hexágono, para hexágonos maiores, pois esse método requer mais espaço para hexágonos maiores (se você deseja manter a precisão por pixel). Para pequenos hexágonos (e dependendo do hardware), esse método é provavelmente mais rápido do que calcular os limites.
Olhovsky
9
Um hexágono é qualquer polígono de 6 lados. O que você está pensando é um equilátero hexágono (na verdade, você está pensando provavelmente de um regulares hexágono, que é um tipo de equilátero e hexágono equiângulo)
Random832
Observe que eu não estava dizendo que sua resposta foi ruim. Eu acho que é uma boa resposta e uma solução que tem seu lugar. Dito isso, eu não escolheria esse método ao invés de calcular os limites do hexágono, como calcular os limites do hexágono em qualquer plataforma moderna, pois calcular os limites é uma maneira muito mais extensível de fazer isso. Por exemplo, digamos que você queira alterar o tamanho do hexágono - agora você precisa reconstruir a imagem? Produzir uma máscara hexagonal de pixel perfeito é uma dor. O fato de você não ter produzido um aqui é uma prova disso, eu acho.
Olhovsky
2
@Olhovsky - Não produzi uma máscara hexagonal perfeita aqui porque estou respondendo perguntas como um serviço comunitário durante meus poucos minutos de pausa enquanto trabalho, e na verdade não estou escrevendo um videogame. O OP estava procurando uma solução com menos matemática, e eu pensei que era legal, então pensei em compartilhar, porque é algo que certamente não teria pensado sozinho.
dlras2
18

Não existe um método XNA que faça um teste de impacto hexagonal.

Este artigo explica como escrever uma função que faz o teste e fornece a função:

Como verificar se um ponto está dentro de um hexágono

Aqui está um resumo desse artigo: caixa de clique hexagonal

E a função que faz o teste é assim:

  1. Teste a caixa delimitadora ao redor do hexágono, logo no início, se não o cruzar.
  2. Transforme o ponto em um quadrante local, como mostrado acima.
  3. Execute o seguinte isInsideteste para o quadrante local.

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;
}

Veja o artigo para detalhes completos.


Aqui estão algumas outras fontes relacionadas úteis:

Olhovsky
fonte
1

Aqui eu tenho um método que pode ser usado para detectar cliques dentro de qualquer polígono:

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;
    }

Você precisa fornecer os cantos do seu hexágono em um vetor2 (poli) e a posição clicada (p) para o método.

chr1s1202
fonte