Riconoscimento di una casella di selezione esagonale


17

Sto lavorando a un gioco che coinvolgerà esagoni rantolanti .

Al momento, ho un'immagine esagonale che sto usando (tutti i lati hanno la stessa lunghezza ... si adatta a un'immagine da 50 x 50 pixel).

Sono un po 'nuovo in C # e davvero nuovo in XNA, ma esiste una sorta di metodo semplice che posso chiamare piuttosto che fare un'istruzione if contorta basata su punti e angoli?


Vedi gamedev.stackexchange.com/questions/6382/… che implementa il rilevamento dei clic esadecimali.
Tim Holt,

4
Ho completamente cercato su Google "esagoni sussultanti" ero tipo "che tipo di esagono è ?!" Suppongo che sto avendo una giornata lenta.
MichaelHouse

2
Cosa succede se si fa clic nel sussulto piuttosto che nell'esagono?
Tim Holt,

1
A seconda delle tue esigenze, farebbe una semplice cerchia solo per un'area di clic. Altrimenti dovrai usare un punto sulla tecnica poligonale come la somma degli avvolgimenti o la somma.
PhilCK,

A meno che la mappa esadecimale non debba essere ruotata arbitrariamente, il punto sul poligono è eccessivo PRINCIPALE. Cosa fai con una mappa di 1000x1000 esagoni? Controlla tutti? RE: Cerchie, non funzioneranno. Vicino al vertice di giunzione tra tre esagoni, avrai tre cerchi sovrapposti. I cerchi più piccoli che si trovano completamente all'interno degli esagoni avranno degli spazi in cui i clic legittimi non saranno presenti in alcun cerchio.
Tim Holt,

Risposte:


18

Un esagono è un rettangolo con angoli ritagliati. Il modo in cui l'ho visto fatto, e ho sentito che la serie Civilization lo fa in questo modo con mappe ortogonali, è creare una bitmap con uno spazio bianco (ortogonale o esagonale) e un rosso, verde, blu e giallo angolo. (O qualunque colore ti piaccia.)

Esagonale: Hex maskoenter image description here

Ortogonale: enter image description here

Quindi, basta determinare su quale rettangolo si trova il cursore e testare il colore del pixel in quella posizione. Se è bianco, si librano su quello spazio. Ogni altro colore è mappato su uno scostamento e al loro posto si librano su quell'esagono. In questo modo è efficiente, richiede poca geometria e può essere utilizzato per qualsiasi spazio arbitrariamente tassellato.


Solo una nota: un esagono ha 6 lati di uguale lunghezza. Nessuna delle immagini presentate contiene effettivamente esagoni. Al contrario, contengono poligoni a 6 lati. A parte questo, questo metodo funziona. È probabilmente più lento rispetto al calcolo dei limiti dell'esagono, per esagoni più grandi, poiché questo metodo richiede più spazio per esagoni più grandi (se si desidera mantenere la precisione per pixel). Per piccoli esagoni (e in base all'hardware), questo metodo è probabilmente più veloce rispetto al calcolo dei limiti.
Olhovsky,

9
Un esagono è un poligono a 6 facce. Quello a cui stai pensando è un esagono equilatero (in realtà, probabilmente stai pensando a un esagono regolare , che è un tipo di esagono equilatero ed equiangolare)
Casuale 832

Tieni presente che non stavo dicendo che la tua risposta era negativa. Penso che sia una buona risposta e una soluzione che abbia il suo posto. Detto questo, non sceglierei questo metodo rispetto al calcolo dei limiti esagonali, poiché calcolare i limiti esagonali su qualsiasi piattaforma moderna, poiché calcolare i limiti è un modo molto più estensibile per farlo. Ad esempio, supponiamo che tu voglia cambiare la dimensione dell'esagono - ora devi ricostruire l'immagine? Produrre una maschera esagonale pixel perfetta è un dolore. Il fatto che tu non ne abbia prodotto uno qui ne è una testimonianza, credo.
Olhovsky,

2
@Olhovsky - Qui non ho prodotto una maschera esagonale perfetta perché sto rispondendo a domande come servizio di comunità durante le mie pause di pochi minuti mentre sono al lavoro e non sto scrivendo un videogioco. L'OP stava cercando una soluzione con meno matematica, e ho pensato che fosse pulito, quindi ho pensato di condividere, perché è qualcosa che sicuramente non avrei pensato da solo.
dlras2,

18

Non esiste un metodo XNA che esegua un test di esagono.

Questo articolo spiega come scrivere una funzione che esegue il test e fornisce la funzione:

Come verificare se un punto si trova all'interno di un esagono

Ecco un riassunto di quell'articolo: casella di selezione esagonale

E la funzione che esegue il test va così:

  1. Prova il rettangolo di selezione attorno all'esagono, in anticipo se non lo interseca.
  2. Trasforma il punto in un quadrante locale come mostrato sopra.
  3. Eseguire il seguente isInsidetest per il quadrante locale.

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

Vedi l'articolo per tutti i dettagli.


Ecco alcune altre utili fonti correlate:


1

Qui ho un metodo che può essere utilizzato per rilevare i clic all'interno di qualsiasi poligono:

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

Devi dare gli angoli del tuo esagono in un array vector2 (poli) e la posizione cliccata (p) al metodo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.