Próbuję stworzyć funkcję piksela do koordynowania dla mapy heksadecymalnej, ale matematyka nie jest poprawnie zrozumiana, wszystko, co próbuję, wydaje się być trochę nie w porządku, a przykłady, które znalazłem, były oparte na mapach z wycentrowanymi kołami.
Przez „oparte na tablicy” rozumiem sposób, w jaki heksy są uporządkowane, patrz rys.
Najdokładniejszy wynik, jaki uzyskałem, dotyczył następującego kodu, ale wciąż jest wyłączony i gorzej, im bardziej rosną wartości:
public HexCell<T> coordsToHexCell(float x, float y){
final float size = this.size; // cell size
float q = (float) ((1f/3f* Math.sqrt(3) * x - 1f/3f * y) / size);
float r = 2f/3f * y / size;
return getHexCell((int) r, (int) q);
}
Ekran zaczyna się od 0,0 w lewym górnym rogu, każda komórka zna swoje centrum.
Potrzebuję tylko sposobu, aby przełożyć współrzędne ekranu na współrzędne szesnastkowe. Jak mogłem to zrobić?
źródło
Moim zdaniem istnieją dwa sposoby rozwiązania tego problemu.
Użyj lepszego układu współrzędnych. Możesz znacznie ułatwić sobie matematykę, jeśli masz sprytne podejście do numerowania heksów. Amit Patel ma ostateczne odniesienie do sześciokątnych siatek. Na tej stronie będziesz szukać współrzędnych osiowych .
Pożycz kod od kogoś, kto już go rozwiązał. Mam trochę działającego kodu , który wziąłem ze źródła Bitwy o Wesnoth . Pamiętaj, że moja wersja ma płaską część heksów na górze, więc będziesz musiał zamienić xiy.
źródło
Myślę, że odpowiedź Michaela Kristofika jest poprawna, szczególnie w przypadku wzmianki o stronie Amit Patel, ale chciałem podzielić się moim nowym podejściem do siatek heksadecymalnych.
Ten kod został zaczerpnięty z projektu, który mnie nie interesuje i porzuciłem w JavaScript, ale pozycja myszy do kafelka hex działała świetnie. Użyłem * tego artykułu GameDev * do moich odniesień. Z tej strony autor miał ten obraz, który pokazał, jak matematycznie przedstawić wszystkie strony i pozycje Hex.
W mojej klasie renderowania miałem to zdefiniowane w metodzie, która pozwoliła mi ustawić dowolną długość boku Hex, którą chciałem. Pokazane tutaj, ponieważ niektóre z tych wartości zostały przywołane w pikselach do kodu współrzędnych szesnastkowych.
W klasie wejściowej myszy stworzyłem metodę, która zaakceptowała współrzędną ekranową xiy i zwróciła obiekt o współrzędnej szesnastkowej, w której znajduje się piksel. * Pamiętaj, że miałem fałszywą „kamerę”, więc uwzględniono również przesunięcia pozycji renderowania.
Wreszcie jest zrzut ekranu mojego projektu z włączonym debugowaniem renderowania. Pokazuje czerwone linie, w których kod sprawdza komórki TypeA i TypeB wraz ze współrzędnymi heksadecymalnymi i konturami komórek.
Mam nadzieję, że to pomaga niektórym.
źródło
Znalazłem rozwiązanie bez matematyki szesnastkowej.
Jak wspomniałem w pytaniu, każda komórka zapisuje swoje własne współrzędne centralne, obliczając najbliższe centrum szesnastkowe względem współrzędnych pikselowych, mogę określić odpowiednią komórkę szesnastkową z dokładnością do pikseli (lub bardzo blisko niej).
Nie sądzę, że jest to najlepszy sposób, aby to zrobić, ponieważ muszę iterować do każdej komórki i widzę, jak to może być opodatkowane, ale pozostawi kod jako alternatywne rozwiązanie:
źródło
0…cols-1
i wszystkie wiersze0…rows-1
, możesz skanowaćcol_guess - 1 … col_guess+1
irow_guess - 1 … row_guess + 1
. To tylko 9 heksów, więc jest szybkie i nie zależy od wielkości mapy.Oto cechy implementacji C # jednej z technik opublikowanych na stronie internetowej Amit Patel (jestem pewien, że tłumaczenie na Javę nie będzie wyzwaniem):
Reszta projektu jest dostępna tutaj jako Open Source, w tym klasy MatrixInt2D i VectorInt2D, o których mowa powyżej:
http://hexgridutilities.codeplex.com/
Chociaż powyższa implementacja dotyczy heksów z płaskimi wierzchołkami, biblioteka HexgridUtilities zawiera opcję transpozycji siatki.
źródło
Znalazłem proste, alternatywne podejście, które wykorzystuje tę samą logikę, co zwykła szachownica. Tworzy efekt przyciągania do siatki z punktami pośrodku każdego kafelka i każdego wierzchołka (tworząc ściślejszą siatkę i ignorując przemienne punkty).
To podejście działa dobrze w grach takich jak Catan, w których gracze wchodzą w interakcję z kafelkami i wierzchołkami, ale nie nadaje się do gier, w których gracze tylko wchodzą w interakcje z kafelkami, ponieważ zwraca to, który punkt środkowy lub wierzchołek są najbliższe, a nie który sześciokąt współrzędne są w środku.
Geometria
Jeśli umieścisz punkty na siatce z kolumnami o ćwiartce szerokości kafelka i rzędami o połowę wysokości kafelka, otrzymasz następujący wzór:
Jeśli następnie zmodyfikujesz kod, aby pomijał każdą sekundę kropki we wzorze szachownicy (pomijanie
if column % 2 + row % 2 == 1
), otrzymujesz następujący wzór:Realizacja
Mając na uwadze tę geometrię, możesz utworzyć tablicę 2D (podobnie jak w przypadku kwadratowej siatki), przechowując
x, y
współrzędne dla każdego punktu na siatce (z pierwszego schematu) - coś takiego:Uwaga: Jak zwykle, gdy tworzysz siatkę wokół punktów (zamiast umieszczania kropek w samych punktach), musisz przesunąć początek (odejmując połowę szerokości kolumny od
x
i połowę wysokości rzęduy
).Po
points
zainicjowaniu tablicy 2D ( ) możesz znaleźć najbliższy punkt myszy, tak jak na kwadratowej siatce, tylko ignorując każdy inny punkt, aby utworzyć wzór na drugim diagramie:To zadziała, ale współrzędne są zaokrąglane do najbliższego punktu (lub żadnego punktu) na podstawie tego, w którym niewidocznym prostokącie znajduje się wskaźnik. Naprawdę chcesz mieć okrągłą strefę wokół punktu (aby zasięg był równy w każdym kierunku). Teraz, gdy wiesz, który punkt sprawdzić, możesz łatwo znaleźć odległość (używając twierdzenia Pitagorasa). Implikowany okrąg nadal musiałby zmieścić się w oryginalnym prostokącie ograniczającym, ograniczając jego maksymalną średnicę do szerokości kolumny (ćwiartka szerokości płytki), ale wciąż jest wystarczająco duży, aby działał dobrze w praktyce.
źródło