Rozpoznawanie sześciokątnego pola kliknięcia


17

Pracuję nad grą, która ma zamiar zaangażować gasp sześciokątów.

Obecnie mam obraz sześciokątny, którego używam (wszystkie boki mają tę samą długość ... pasuje do obrazu 50 na 50 pikseli).

Jestem trochę nowy w C # i naprawdę nowy w XNA, ale czy jest jakaś prosta metoda, którą mogę wywołać, zamiast wykonywać zawiłe, jeśli zdanie oparte na punktach i kątach?


Zobacz gamedev.stackexchange.com/questions/6382/..., który implementuje wykrywanie kliknięć heksadecymalnych.
Tim Holt

4
Całkowicie googlowałem „dysząc sześciokąty”, pomyślałem: „co to za sześciokąt ?!” Chyba mam wolny dzień.
MichaelHouse

2
Hmm, co się stanie, jeśli klikniesz oddech, a nie sześciokąt?
Tim Holt

1
W zależności od potrzeb wystarczy prosty okrąg, który służy tylko do kliknięcia. W przeciwnym razie będziesz musiał użyć punktu w technice wielokąta, takiego jak suma uzwojenia lub sumsuch.
PhilCK

O ile mapa heksadecymalna nie zostanie dowolnie obrócona, punkt na wielokącie jest OGROMNYM nadmiarem. Co robisz z mapą o wymiarach 1000 x 1000 heksów? Sprawdź każdy? RE: Koła, nie będą działać. W pobliżu wierzchołka skrzyżowania między trzema heksami będą się nakładać trzy koła. Mniejsze kręgi, które leżą całkowicie w obrębie heksów, będą miały luki, w których prawidłowe kliknięcia nie będą w żadnym okręgu.
Tim Holt

Odpowiedzi:


18

Sześciokąt to prostokąt z obciętymi narożnikami. Sposób, w jaki to widziałem i słyszałem, że seria Civilization robi to w ten sposób z mapami ortogonalnymi, polega na utworzeniu mapy bitowej z białą przestrzenią (ortogonalną lub heksagonalną) oraz czerwoną, zieloną, niebieską i żółtą kąt. (Lub jakikolwiek inny kolor).

Sześciokątny: Hex masklubenter image description here

Prostokątny: enter image description here

Następnie po prostu określ, na którym prostokącie znajduje się kursor, i przetestuj kolor piksela w tym miejscu. Jeśli jest biały, unoszą się nad tą przestrzenią. Każdy inny kolor jest odwzorowany na przesunięcie i zamiast tego najeżdżają na ten sześciokąt. Ten sposób jest wydajny, wymaga niewielkiej geometrii i może być wykorzystywany do dowolnej przestrzeni mozaikowej.


Tylko uwaga: sześciokąt ma 6 boków o równej długości. Żaden z prezentowanych obrazów nie zawiera sześciokątów. Zamiast tego zawierają 6-stronne wielokąty. Poza tym ta metoda działa. Jest to prawdopodobnie wolniejsze niż obliczanie granic sześciokąta, jednak w przypadku większych sześciokątów ta metoda wymaga więcej miejsca na większe sześciokąty (jeśli chcesz zachować dokładność na piksel). W przypadku małych sześciokątów (w zależności od sprzętu) ta metoda jest prawdopodobnie szybsza niż obliczanie granic.
Olhovsky

9
Sześciokąt to dowolny wielokąt 6-stronny. To, o czym myślisz, to sześciokąt równoboczny (w rzeczywistości prawdopodobnie myślisz o zwykłym sześciokącie, który jest rodzajem sześciokąta równobocznego i równokątnego)
Random832

Pamiętaj, że nie mówiłem, że twoja odpowiedź była zła. Myślę, że to dobra odpowiedź i rozwiązanie, które ma swoje miejsce. To powiedziawszy, nie wybrałbym tej metody zamiast obliczania granic sześciokąta, ponieważ obliczanie granic sześciokąta na dowolnej współczesnej platformie, ponieważ obliczanie granic jest znacznie bardziej rozszerzalnym sposobem. Np. Powiedzmy, że chcesz zmienić rozmiar sześciokąta - teraz musisz odbudować obraz? Wytworzenie idealnej pikselowej maski sześciokątnej jest uciążliwe. Myślę, że fakt, że nie stworzyłeś go tutaj, świadczy o tym.
Olhovsky

2
@Olhovsky - Nie stworzyłem tutaj idealnej maski sześciokątnej, ponieważ odpowiadam na pytania jako usługa społecznościowa podczas moich kilku minutowych przerw w pracy, a nie piszę gry wideo. OP szukał rozwiązania o mniejszej matematyce i pomyślałem, że to fajne, więc pomyślałem, że podzielę się, ponieważ z pewnością nie wymyśliłbym tego samodzielnie.
dlras2

18

Nie ma metody XNA, która wykonuje test trafienia w sześciokąt.

W tym artykule wyjaśniono, jak napisać funkcję wykonującą test, i podano jej funkcję:

Jak sprawdzić, czy punkt znajduje się w sześciokącie

Oto streszczenie tego artykułu: sześciokątne pole kliknięcia

Funkcja, która wykonuje test, wygląda następująco:

  1. Przetestuj obwiednię wokół sześciokąta, wcześniej, jeśli się nie przecina.
  2. Przekształć punkt w lokalny kwadrant, jak pokazano powyżej.
  3. Wykonaj następujący isInsidetest dla lokalnej ćwiartki.

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

Zobacz artykuł, aby uzyskać szczegółowe informacje.


Oto kilka innych przydatnych powiązanych źródeł:


1

Oto metoda, której można użyć do wykrywania kliknięć wewnątrz dowolnego wielokąta:

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

Musisz podać rogi sześciokąta w tablicy vector2 (poli) i pozycję kliknięcia (p) metodzie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.