Ich versuche, eine Pixel-zu-Koordinaten-Funktion für eine Hex-Karte zu erstellen, aber ich verstehe die Mathematik nicht richtig. Alles, was ich versuche, scheint ein wenig anders zu sein, und die Beispiele, die ich gefunden habe, basieren auf eingekreisten zentrierten Karten.
Mit 'Array-basiert' meine ich die Art und Weise, wie die Hexes geordnet sind, siehe Bild.
Das genaueste Ergebnis, das ich erhalten habe, war mit dem folgenden Code, aber er ist immer noch deaktiviert und wird umso schlimmer, je mehr die Werte steigen:
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);
}
Der Bildschirm beginnt mit 0,0 oben links, jede Zelle kennt ihre Mitte.
Ich brauche nur eine Möglichkeit, Bildschirmkoordinaten in Hex-Koordinaten zu übersetzen. Wie könnte ich das machen?
quelle
Meiner Meinung nach gibt es zwei Möglichkeiten, um mit diesem Problem umzugehen.
Verwenden Sie ein besseres Koordinatensystem. Sie können sich die Mathematik viel leichter machen, wenn Sie klug sind, wie Sie die Felder nummerieren. Amit Patel hat die endgültige Referenz für hexagonale Gitter. Auf dieser Seite sollten Sie nach axialen Koordinaten suchen .
Leihen Sie sich Code von jemandem aus, der ihn bereits gelöst hat. Ich habe einen Code , der funktioniert und den ich aus der Quelle Battle for Wesnoth entnommen habe . Denken Sie daran, dass meine Version den flachen Teil der Felder oben hat, so dass Sie x und y tauschen müssen.
quelle
Ich denke, Michael Kristofiks Antwort ist richtig, insbesondere, weil er die Website von Amit Patel erwähnt hat, aber ich wollte meinen neuen Ansatz für Hex-Gitter teilen.
Dieser Code stammt aus einem Projekt, an dem ich das Interesse verloren habe und das ich in JavaScript aufgegeben habe , aber die Mausposition für Hex-Kacheln hat hervorragend funktioniert. Ich habe * diesen GameDev-Artikel * für meine Referenzen verwendet. Von dieser Website hatte der Autor dieses Bild, das zeigte, wie alle Hex-Seiten und -Positionen mathematisch dargestellt werden können.
In meiner Renderklasse hatte ich dies in einer Methode definiert, mit der ich jede gewünschte Hex-Seitenlänge einstellen konnte. Hier gezeigt, weil einige dieser Werte im Pixel-Hex-Koordinatencode referenziert wurden.
In der Mauseingabeklasse habe ich eine Methode erstellt, die eine x- und y-Koordinate des Bildschirms akzeptiert, und ein Objekt mit der Hex-Koordinate zurückgegeben, in der sich das Pixel befindet. * Beachten Sie, dass ich eine gefälschte "Kamera" hatte, so dass auch Offsets für die Renderposition enthalten sind.
Zum Schluss hier ein Screenshot meines Projekts mit aktiviertem Debug des Renderings. Es zeigt die roten Linien, in denen der Code nach TypeA- und TypeB-Zellen sucht, zusammen mit den Hex-Koordinaten und Zellumrissen. Ich
hoffe, dies hilft einigen.
quelle
Ich habe tatsächlich eine Lösung ohne Hex-Mathematik gefunden.
Wie ich in der Frage erwähnt habe, speichert jede Zelle ihre eigenen Mittenkoordinaten. Durch Berechnen der Hex-Mitte, die den Pixelkoordinaten am nächsten liegt, kann ich die entsprechende Hex-Zelle mit Pixelgenauigkeit (oder sehr nahe daran) bestimmen.
Ich denke nicht, dass dies der beste Weg ist, da ich zu jeder Zelle iterieren muss und sehen kann, wie anstrengend das sein könnte, aber den Code als alternative Lösung belassen wird:
quelle
0…cols-1
und Zeilen zu0…rows-1
scannen, können Siecol_guess - 1 … col_guess+1
und scannenrow_guess - 1 … row_guess + 1
. Das sind nur 9 Felder, also schnell und unabhängig von der Größe der Karte.Hier ist der Mut einer C # -Implementierung einer der auf der Amit Patel-Website veröffentlichten Techniken (ich bin sicher, dass das Übersetzen in Java keine Herausforderung darstellt):
Der Rest des Projekts ist hier als Open Source verfügbar, einschließlich der oben genannten Klassen MatrixInt2D und VectorInt2D:
http://hexgridutilities.codeplex.com/
Obwohl die obige Implementierung für Hexes mit flachen Spitzen gilt, enthält die HexgridUtilities-Bibliothek die Option, das Gitter zu transponieren.
quelle
Ich habe einen einfachen, alternativen Ansatz gefunden, der dieselbe Logik wie ein normales Schachbrett verwendet. Es wird ein Rastereffekt mit Punkten in der Mitte jeder Kachel und an jedem Scheitelpunkt erstellt (indem ein engeres Raster erstellt und abwechselnde Punkte ignoriert werden).
Dieser Ansatz eignet sich gut für Spiele wie Catan, bei denen Spieler mit Kacheln und Scheitelpunkten interagieren. Er eignet sich jedoch nicht für Spiele, bei denen Spieler nur mit Kacheln interagieren, da er zurückgibt, welchem Mittelpunkt oder Scheitelpunkt die Koordinaten am nächsten liegen und nicht welcher sechseckigen Kachel Koordinaten sind innerhalb.
Die Geometrie
Wenn Sie Punkte in einem Raster mit Spalten platzieren, die viertel der Breite einer Kachel entsprechen, und Zeilen, die die halbe Höhe einer Kachel haben, erhalten Sie folgendes Muster:
Wenn Sie dann den Code so ändern, dass jeder zweite Punkt in einem Schachbrettmuster übersprungen wird (Überspringen
if column % 2 + row % 2 == 1
), erhalten Sie folgendes Muster:Implementierung
Unter Berücksichtigung dieser Geometrie können Sie ein 2D-Array erstellen (genau wie bei einem quadratischen Raster) und die
x, y
Koordinaten für jeden Punkt im Raster (aus dem ersten Diagramm) speichern - ungefähr so:Hinweis: Wenn Sie ein Raster um die Punkte erstellen (anstatt Punkte an den Punkten selbst zu platzieren), müssen Sie wie gewohnt den Ursprung versetzen (indem Sie die Hälfte der Breite einer Spalte von
x
und die Hälfte der Höhe einer Zeile von subtrahiereny
).Nachdem Sie Ihr 2D-Array (
points
) initialisiert haben, können Sie den Punkt finden, der der Maus am nächsten liegt, genau wie in einem quadratischen Raster. Sie müssen nur jeden anderen Punkt ignorieren, um das Muster im zweiten Diagramm zu erstellen:Das wird funktionieren, aber die Koordinaten werden auf den nächsten Punkt (oder keinen Punkt) gerundet, basierend auf dem unsichtbaren Rechteck, in dem sich der Zeiger befindet. Sie möchten wirklich eine kreisförmige Zone um den Punkt (also ist der Fangbereich in jeder Richtung gleich). Nachdem Sie nun wissen, welchen Punkt Sie überprüfen müssen, können Sie die Entfernung leicht ermitteln (mithilfe des Satzes von Pythagoras). Der implizite Kreis müsste immer noch in das ursprüngliche Begrenzungsrechteck passen und seinen maximalen Durchmesser auf die Breite einer Säule (Viertel der Breite einer Kachel) beschränken, aber das ist immer noch groß genug, um in der Praxis gut zu funktionieren.
quelle