Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Tile-Based Games

Einführung in Axialkoordinaten für hexagonale kachelbasierte Spiele

by
Read Time:12 minsLanguages:

German (Deutsch) translation by Valentina (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

Der grundlegende Ansatz auf der Basis hexagonaler Kacheln, der im Tutorial zum hexagonalen Minensuchboot erläutert wird, erledigt die Arbeit, ist jedoch nicht sehr effizient. Es verwendet eine direkte Konvertierung aus den zweidimensionalen Array-basierten Level-Daten und den Bildschirmkoordinaten, was die Bestimmung von gekappten Kacheln unnötig kompliziert macht.

Außerdem ist es nicht zweckmäßig, je nach ungerader oder gerader Zeile/Spalte einer Kachel unterschiedliche Logik zu verwenden. In dieser Lernprogrammreihe werden die alternativen Bildschirmkoordinatensysteme untersucht, mit denen die Logik vereinfacht und die Arbeit erleichtert werden kann. Ich würde Ihnen dringend empfehlen, das Tutorial zum sechseckigen Minenräumer zu lesen, bevor Sie mit diesem Tutorial fortfahren, da dort das Raster-Rendering auf der Basis eines zweidimensionalen Arrays erklärt wird.

1. Axialkoordinaten

Der Standardansatz für Bildschirmkoordinaten im Tutorial zum hexagonalen Minensuchboot wird als Versatzkoordinatenansatz bezeichnet. Dies liegt daran, dass die alternativen Zeilen oder Spalten beim Ausrichten des hexagonalen Gitters um einen Wert versetzt werden.

Informationen zum Aktualisieren Ihres Speichers finden Sie in der Abbildung unten, in der die horizontale Ausrichtung mit den angezeigten Versatzkoordinatenwerten dargestellt ist.

horizontally aligned hexagonal grid with offset coordinate valueshorizontally aligned hexagonal grid with offset coordinate valueshorizontally aligned hexagonal grid with offset coordinate values

Im obigen Bild wird eine Zeile mit demselben i-Wert rot und eine Spalte mit demselben j-Wert grün hervorgehoben. Um alles einfach zu machen, werden wir nicht auf die ungeraden und geraden Offset-Varianten eingehen, da beide nur unterschiedliche Wege sind, um das gleiche Ergebnis zu erzielen.

Lassen Sie mich eine bessere Alternative für die Bildschirmkoordinate vorstellen, die Axialkoordinate. Das Konvertieren einer Versatzkoordinate in eine axiale Variante ist sehr einfach. Der i-Wert bleibt gleich, aber der j-Wert wird mit der Formel axialJ = i - floor(j/2) konvertiert. Eine einfache Methode kann verwendet werden, um einen versetzten Phaser.Point in seine axiale Variante zu konvertieren, wie unten gezeigt.

Die umgekehrte Umwandlung wäre wie unten gezeigt.

Hier ist der x-Wert der i-Wert und der y-Wert der j-Wert für das zweidimensionale Array. Nach der Konvertierung sehen die neuen Werte wie im Bild unten aus.

horizontally aligned hexagonal grid with axial coordinate valueshorizontally aligned hexagonal grid with axial coordinate valueshorizontally aligned hexagonal grid with axial coordinate values

Beachten Sie, dass die grüne Linie, bei der der j-Wert gleich bleibt, nicht mehr im Zickzack verläuft, sondern jetzt eine Diagonale zu unserem hexagonalen Gitter darstellt.

Für das vertikal ausgerichtete hexagonale Gitter werden die Versatzkoordinaten im Bild unten angezeigt.

vertically aligned hexagonal grid with offset coordinate valuesvertically aligned hexagonal grid with offset coordinate valuesvertically aligned hexagonal grid with offset coordinate values

Die Umrechnung in Axialkoordinaten folgt denselben Gleichungen, mit dem Unterschied, dass wir den j-Wert gleich halten und den i-Wert ändern. Die folgende Methode zeigt die Konvertierung.

Das Ergebnis ist wie unten gezeigt.

vertically aligned hexagonal grid with axial coordinate valuesvertically aligned hexagonal grid with axial coordinate valuesvertically aligned hexagonal grid with axial coordinate values

Bevor wir die neuen Koordinaten zur Lösung von Problemen verwenden, möchte ich Ihnen kurz eine andere Alternative für Bildschirmkoordinaten vorstellen: Würfelkoordinaten.

2. Würfel oder kubische Koordinaten

Das Aufrichten des Zickzacks selbst hat möglicherweise die meisten Unannehmlichkeiten gelöst, die wir mit dem Versatzkoordinatensystem hatten. Würfel oder kubische Koordinaten würden uns weiter dabei helfen, komplizierte Logik wie Heuristiken oder das Drehen um eine hexagonale Zelle zu vereinfachen.

Wie Sie vielleicht anhand des Namens erraten haben, hat das kubische System drei Werte. Der dritte k- oder z-Wert wird aus der Gleichung x+y+z=0 abgeleitet, wobei x und y die axialen Koordinaten sind. Dies führt uns zu dieser einfachen Methode zur Berechnung des z-Wertes.

Die Gleichung x+y+z=0 ist eigentlich eine 3D-Ebene, die durch die Diagonale eines dreidimensionalen Würfelgitters verläuft. Wenn Sie alle drei Werte für das Raster anzeigen, werden die folgenden Bilder für die verschiedenen hexagonalen Ausrichtungen angezeigt.

horizontally aligned hexagonal grid with cube coordinate valueshorizontally aligned hexagonal grid with cube coordinate valueshorizontally aligned hexagonal grid with cube coordinate values
vertically aligned hexagonal grid with cube coordinate valuesvertically aligned hexagonal grid with cube coordinate valuesvertically aligned hexagonal grid with cube coordinate values

Die blaue Linie zeigt die Kacheln an, bei denen der z-Wert gleich bleibt.

3. Vorteile des neuen Koordinatensystems

Sie fragen sich vielleicht, wie diese neuen Koordinatensysteme uns bei der hexagonalen Logik helfen. Ich werde einige Vorteile erläutern, bevor wir mit unserem neuen Wissen einen sechseckigen Tetris erstellen.

Bewegung

Betrachten wir die mittlere Kachel im obigen Bild mit kubischen Koordinatenwerten von 3,6,-9. Wir haben festgestellt, dass ein Koordinatenwert für die Kacheln auf den farbigen Linien gleich bleibt. Ferner können wir sehen, dass die verbleibenden Koordinaten entweder um 1 zunehmen oder abnehmen, während eine der farbigen Linien verfolgt wird. Wenn beispielsweise der x-Wert gleich bleibt und der y-Wert entlang einer Richtung um 1 zunimmt, nimmt der z-Wert um 1 ab, um unsere maßgebliche Gleichung x+y+z=0 zu erfüllen. Diese Funktion erleichtert die Bewegungssteuerung erheblich. Wir werden dies im zweiten Teil der Serie verwenden.

Nachbarn

Nach der gleichen Logik ist es einfach, die Nachbarn für die Kacheln x,y,z zu finden. Wenn wir x gleich halten, erhalten wir zwei diagonale Nachbarn, x,y-1,z+1 und x,y+1,z-1. Wenn y gleich bleibt, erhalten wir zwei vertikale Nachbarn, x-1,y,z+1 und x+1,y,z-1. Wenn wir z gleich halten, erhalten wir die verbleibenden zwei diagonalen Nachbarn x+1,y-1,z und x-1,y+1,z. Das Bild unten zeigt dies für eine Kachel am Ursprung.

the cube coordinates of neighbours of a hexagonal tile at originthe cube coordinates of neighbours of a hexagonal tile at originthe cube coordinates of neighbours of a hexagonal tile at origin

Es ist jetzt so viel einfacher, dass wir keine andere Logik verwenden müssen, die auf geraden oder ungeraden Zeilen/Spalten basiert.

Sich um eine Fliese bewegen

Eine interessante Sache, die im obigen Bild zu bemerken ist, ist eine Art zyklische Symmetrie für alle Kacheln um die rote Kachel herum. Wenn wir die Koordinaten einer benachbarten Kachel nehmen, können die Koordinaten der unmittelbar benachbarten Kachel erhalten werden, indem die Koordinatenwerte entweder links oder rechts durchlaufen und dann mit -1 multipliziert werden.

Zum Beispiel hat der obere Nachbar einen Wert von -1,0,1, der beim Drehen nach rechts einmal zu 1,-1,0 und nach dem Multiplizieren mit -1 zu -1,1,0 wird, was die Koordinate von rechts ist Nachbar. Wenn Sie nach links drehen und mit -1 multiplizieren, erhalten Sie 0,-1,1, die Koordinate des linken Nachbarn. Wenn Sie dies wiederholen, können Sie zwischen allen benachbarten Kacheln um die mittlere Kachel springen. Dies ist eine sehr interessante Funktion, die bei Logik und Algorithmen hilfreich sein kann.

Beachten Sie, dass dies nur aufgrund der Tatsache geschieht, dass die mittlere Kachel als Ursprung betrachtet wird. Wir könnten leicht jede Kachel x,y,z zum Ursprung machen, indem wir die Werte x, y und z von ihr und allen anderen Kacheln subtrahieren.

Heuristik

Die Berechnung effizienter Heuristiken ist der Schlüssel für die Pfadfindung oder ähnliche Algorithmen. Kubische Koordinaten erleichtern aufgrund der oben genannten Aspekte das Auffinden einfacher Heuristiken für hexagonale Gitter. Wir werden dies im zweiten Teil dieser Reihe ausführlich diskutieren.

Dies sind einige der Vorteile des neuen Koordinatensystems. Wir könnten in unseren praktischen Implementierungen eine Mischung der verschiedenen Koordinatensysteme verwenden. Beispielsweise ist das zweidimensionale Array immer noch der beste Weg, um die Ebenendaten zu speichern, deren Koordinaten die Versatzkoordinaten sind.

Versuchen wir, mit diesem neuen Wissen eine sechseckige Version des berühmten Tetris-Spiels zu erstellen.

4. Erstellen eines hexagonalen Tetris

Wir haben alle Tetris gespielt, und wenn Sie ein Spieleentwickler sind, haben Sie möglicherweise auch Ihre eigene Version erstellt. Tetris ist eines der einfachsten Spiele auf Kachelbasis, das man neben Tic Tac Toe oder Checkers mit einem einfachen zweidimensionalen Array implementieren kann. Lassen Sie uns zunächst die Funktionen von Tetris auflisten.

  • Es beginnt mit einem leeren zweidimensionalen Gitter.
  • Oben erscheinen verschiedene Blöcke, die sich jeweils um ein Plättchen nach unten bewegen, bis sie unten ankommen.
  • Sobald sie den Boden erreicht haben, werden sie dort zementiert oder werden nicht interaktiv. Grundsätzlich werden sie Teil des Rasters.
  • Während des Herunterfallens kann der Block seitwärts bewegt, im Uhrzeigersinn/gegen den Uhrzeigersinn gedreht und heruntergefallen werden.
  • Das Ziel ist es, alle Kacheln in einer Reihe zu füllen, auf der die gesamte Reihe verschwindet, und den Rest des gefüllten Gitters darauf zu kollabieren.
  • Das Spiel endet, wenn keine freien Kacheln mehr oben sind, damit ein neuer Block in das Gitter aufgenommen werden kann.

Darstellung der verschiedenen Blöcke

Da das Spiel Blöcke hat, die vertikal abfallen, verwenden wir ein vertikal ausgerichtetes hexagonales Gitter. Dies bedeutet, dass sie durch seitliches Bewegen im Zickzack bewegt werden. Eine vollständige Zeile im Raster besteht aus einer Reihe von Kacheln in Zick-Zack-Reihenfolge. Ab diesem Zeitpunkt können Sie sich auf den Quellcode beziehen, der zusammen mit diesem Lernprogramm bereitgestellt wird.

Die Ebenendaten werden in einem zweidimensionalen Array mit dem Namen levelData gespeichert, und das Rendern erfolgt unter Verwendung der Versatzkoordinaten, wie im Tutorial zum hexagonalen Minensuchboot erläutert. Bitte beziehen Sie sich darauf, wenn Sie Schwierigkeiten haben, dem Code zu folgen.

Das interaktive Element im nächsten Abschnitt zeigt die verschiedenen Blöcke, die wir verwenden werden. Es gibt noch einen zusätzlichen Block, der aus drei gefüllten Kacheln besteht, die vertikal wie eine Säule ausgerichtet sind. BlockData wird verwendet, um die verschiedenen Blöcke zu erstellen.

Eine leere Blockvorlage besteht aus sieben Kacheln, die aus einer mittleren Kachel bestehen, die von ihren sechs Nachbarn umgeben ist. Für jeden Tetris-Block wird die mittlere Kachel immer mit einem Wert von 1 gefüllt, während eine leere Kachel mit einem Wert von 0 bezeichnet wird. Die verschiedenen Blöcke werden durch Auffüllen der Kacheln von BlockData wie folgt erstellt.

Wir haben insgesamt sieben verschiedene Blöcke.

Blöcke drehen

Lassen Sie mich Ihnen anhand des folgenden interaktiven Elements zeigen, wie sich die Blöcke drehen. Tippen und halten Sie, um die Blöcke zu drehen, und tippen Sie auf x, um die Drehrichtung zu ändern.

Um den Block zu drehen, müssen wir alle Kacheln mit dem Wert 1 finden, den Wert auf 0 setzen, einmal um die mittlere Kachel drehen, um die benachbarte Kachel zu finden, und ihren Wert auf 1 setzen. Um eine Kachel um eine andere Kachel zu drehen, können Sie die Logik verwenden, die im Abschnitt "Bewegen um eine Kachel" oben erläutert wurde. Zu diesem Zweck kommen wir zu der folgenden Methode.

Die Variable clockWise wird verwendet, um im Uhrzeigersinn oder gegen den Uhrzeigersinn zu drehen. Dies wird erreicht, indem die Array-Werte in arrayRotate in entgegengesetzte Richtungen verschoben werden.

Block verschieben

Wir verfolgen die i- und j-Versatzkoordinaten für die mittlere Kachel des Blocks mit den Variablen blockMidRowValue bzw. blockMidColumnValue. Um den Block zu verschieben, erhöhen oder verringern wir diese Werte. Wir aktualisieren die entsprechenden Werte in levelData mit den Blockwerten unter Verwendung der paintBlock-Methode. Die aktualisierten levelData werden verwendet, um die Szene nach jeder Statusänderung zu rendern.

Hier zeigt currentBlock auf die blockData in der Szene. In paintBlock setzen wir zuerst den levelData-Wert für die mittlere Kachel des Blocks auf 1, da er für alle Blöcke immer 1 ist. Der Index des Mittelpunkts lautet blockMidRowValue, blockMidColumnValue.

Dann bewegen wir uns zum levelData-Index der Kachel über der mittleren Kachel blockMidRowValue-1, blockMidColumnValue, und setzen ihn auf 1, wenn der Block diese Kachel als 1 hat. Dann drehen wir uns einmal im Uhrzeigersinn um die mittlere Kachel, um die nächste Kachel zu erhalten, und wiederholen den gleichen Vorgang. Dies erfolgt für alle Kacheln um die mittlere Kachel für den Block.

Überprüfen gültiger Vorgänge

Während wir den Block bewegen oder drehen, müssen wir prüfen, ob dies eine gültige Operation ist. Zum Beispiel können wir den Block nicht bewegen oder drehen, wenn die zu besetzenden Kacheln bereits belegt sind. Außerdem können wir den Block nicht außerhalb unseres zweidimensionalen Gitters verschieben. Wir müssen auch prüfen, ob der Block weiter fallen kann, was bestimmen würde, ob wir den Block zementieren müssen oder nicht.

Für all dies verwende ich eine Methode canMove (i, j), die einen Booleschen Wert zurückgibt, der angibt, ob das Platzieren des Blocks bei i,j eine gültige Verschiebung ist. Bevor wir die levelData-Werte tatsächlich ändern, prüfen wir bei jeder Operation mit dieser Methode, ob die neue Position für den Block eine gültige Position ist.

Der Vorgang hier ist der gleiche wie bei paintBlock, aber anstatt Werte zu ändern, wird nur ein Boolescher Wert zurückgegeben, der eine gültige Verschiebung angibt. Obwohl ich die Drehung um eine mittlere Kachel-Logik verwende, um die Nachbarn zu finden, besteht die einfachere und effizientere Alternative darin, die direkten Koordinatenwerte der Nachbarn zu verwenden, die leicht aus den mittleren Kachelkoordinaten bestimmt werden können.

Das Spiel rendern

Das Spiellevel wird visuell durch eine RenderTexture namens gameScene dargestellt. In den Array-LevelData hätte eine nicht belegte Kachel den Wert 0 und eine belegte Kachel den Wert 2 oder höher.

Ein zementierter Block wird mit einem Wert von 2 bezeichnet, und ein Wert von 5 bezeichnet eine Kachel, die entfernt werden muss, da sie Teil einer fertigen Reihe ist. Ein Wert von 1 bedeutet, dass die Kachel Teil des Blocks ist. Nach jeder Änderung des Spielstatus rendern wir das Level mithilfe der Informationen in levelData, wie unten gezeigt.

Daher wird ein Wert von 0 ohne Farbton gerendert, ein Wert von 1 wird mit einem roten Farbton gerendert, ein Wert von 2 wird mit einem blauen Farbton gerendert und ein Wert von 5 wird mit einem grünen Farbton gerendert.

5. Das abgeschlossene Spiel

Wenn wir alles zusammenfügen, erhalten wir das fertige sechseckige Tetris-Spiel. Bitte gehen Sie den Quellcode durch, um die vollständige Implementierung zu verstehen. Sie werden feststellen, dass wir sowohl Versatzkoordinaten als auch kubische Koordinaten für unterschiedliche Zwecke verwenden. Um beispielsweise festzustellen, ob eine Zeile abgeschlossen ist, verwenden wir Versatzkoordinaten und überprüfen die levelData-Zeilen.

Abschluss

Damit ist der erste Teil der Reihe abgeschlossen. Wir haben erfolgreich ein hexagonales Tetris-Spiel mit einer Kombination aus Versatzkoordinaten, Axialkoordinaten und Würfelkoordinaten erstellt.

Im abschließenden Teil der Serie lernen wir die Bewegung von Charakteren anhand der neuen Koordinaten in einem horizontal ausgerichteten hexagonalen Gitter kennen.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.