Update: Karten-Rendering-Algorithmus korrigiert, weitere Abbildungen hinzugefügt, Formatierung geändert.
Vielleicht kann der Vorteil der "Zick-Zack" -Technik zum Zuordnen der Kacheln zum Bildschirm darin bestehen, dass sich die Kacheln x
und y
Koordinaten auf der vertikalen und horizontalen Achse befinden.
Ansatz "Zeichnen in einem Diamanten":
Durch Zeichnen einer isometrischen Karte mit "Zeichnen in einem Diamanten", was sich meines Erachtens darauf bezieht, die Karte nur mit einer verschachtelten for
Schleife über dem zweidimensionalen Array zu rendern, wie in diesem Beispiel:
tile_map[][] = [[...],...]
for (cellY = 0; cellY < tile_map.size; cellY++):
for (cellX = 0; cellX < tile_map[cellY].size cellX++):
draw(
tile_map[cellX][cellY],
screenX = (cellX * tile_width / 2) + (cellY * tile_width / 2)
screenY = (cellY * tile_height / 2) - (cellX * tile_height / 2)
)
Vorteil:
Der Vorteil des Ansatzes besteht darin, dass es sich um eine einfache verschachtelte for
Schleife mit ziemlich einfacher Logik handelt, die in allen Kacheln konsistent funktioniert.
Nachteil:
Ein Nachteil dieses Ansatzes besteht darin, dass die x
und y
Koordinaten der Kacheln auf der Karte in diagonalen Linien zunehmen, was es möglicherweise schwieriger macht, die Position auf dem Bildschirm visuell auf die als Array dargestellte Karte abzubilden:
Die Implementierung des obigen Beispielcodes wird jedoch eine Gefahr darstellen. Die Renderreihenfolge führt dazu, dass Kacheln, die sich hinter bestimmten Kacheln befinden sollen, über die Kacheln vor ihnen gezeichnet werden:
Um dieses Problem zu for
beheben, muss die Reihenfolge der inneren Schleife umgekehrt werden - beginnend mit dem höchsten Wert und gerendert in Richtung des niedrigeren Werts:
tile_map[][] = [[...],...]
for (i = 0; i < tile_map.size; i++):
for (j = tile_map[i].size; j >= 0; j--): // Changed loop condition here.
draw(
tile_map[i][j],
x = (j * tile_width / 2) + (i * tile_width / 2)
y = (i * tile_height / 2) - (j * tile_height / 2)
)
Mit dem obigen Fix sollte das Rendern der Karte korrigiert werden:
"Zick-Zack" -Ansatz:
Vorteil:
Möglicherweise besteht der Vorteil des "Zick-Zack" -Ansatzes darin, dass die gerenderte Karte vertikal etwas kompakter erscheint als der "Diamant" -Ansatz:
Nachteil:
Beim Versuch, die Zick-Zack-Technik zu implementieren, kann der Nachteil sein, dass es etwas schwieriger ist, den Rendering-Code zu schreiben, da er nicht so einfach wie eine verschachtelte for
Schleife über jedes Element in einem Array geschrieben werden kann:
tile_map[][] = [[...],...]
for (i = 0; i < tile_map.size; i++):
if i is odd:
offset_x = tile_width / 2
else:
offset_x = 0
for (j = 0; j < tile_map[i].size; j++):
draw(
tile_map[i][j],
x = (j * tile_width) + offset_x,
y = i * tile_height / 2
)
Es kann auch etwas schwierig sein, die Koordinate einer Kachel zu ermitteln, da die Renderreihenfolge versetzt ist:
Hinweis: Die in dieser Antwort enthaltenen Abbildungen wurden mit einer Java-Implementierung des dargestellten Kachel-Rendering-Codes mit dem folgenden int
Array als Karte erstellt:
tileMap = new int[][] {
{0, 1, 2, 3},
{3, 2, 1, 0},
{0, 0, 1, 1},
{2, 2, 3, 3}
};
Die Kachelbilder sind:
tileImage[0] ->
Eine Kiste mit einer Kiste darin.
tileImage[1] ->
Eine Blackbox.
tileImage[2] ->
Eine weiße Kiste.
tileImage[3] ->
Eine Kiste mit einem hohen grauen Gegenstand.
Ein Hinweis zu Fliesenbreiten und -höhen
Die Variablen tile_width
und tile_height
die in den obigen Code Beispielen verwendet werden , beziehen sich auf die Breite und die Höhe der Bodenfliese in dem Bild , die die Fliese:
Die Verwendung der Bildabmessungen funktioniert, solange die Bildabmessungen und die Kachelabmessungen übereinstimmen. Andernfalls könnte die Kachelkarte mit Lücken zwischen den Kacheln gerendert werden.
j = (2 * x - 4 * y) / tilewidth * 0.5; i = (p.x * 2 / tilewidth) - j;
.In beiden Fällen wird die Arbeit erledigt. Ich gehe davon aus, dass Sie mit Zickzack so etwas meinen: (Zahlen sind in der Reihenfolge des Renderns)
Und mit Diamant meinst du:
Bei der ersten Methode müssen mehr Kacheln gerendert werden, damit der gesamte Bildschirm gezeichnet wird. Sie können jedoch problemlos eine Grenzüberprüfung durchführen und alle Kacheln vollständig außerhalb des Bildschirms überspringen. Beide Methoden erfordern eine gewisse Zahlenkalkulation, um herauszufinden, wo sich die Kachel 01 befindet. Letztendlich sind beide Methoden in Bezug auf die Mathematik, die für ein bestimmtes Effizienzniveau erforderlich ist, ungefähr gleich.
quelle
Wenn Sie einige Kacheln haben, die die Grenzen Ihres Diamanten überschreiten, empfehle ich, in Tiefenreihenfolge zu zeichnen:
quelle
Coobirds Antwort ist die richtige, vollständige. Ich habe seine Hinweise jedoch mit denen einer anderen Website kombiniert, um Code zu erstellen, der in meiner App (iOS / Objective-C) funktioniert und den ich mit allen teilen möchte, die hierher kommen und nach so etwas suchen. Bitte, wenn Sie diese Antwort mögen / abstimmen, machen Sie dasselbe für die Originale; Alles, was ich tat, war "auf den Schultern von Riesen zu stehen".
Was die Sortierreihenfolge betrifft, ist meine Technik ein modifizierter Malalgorithmus: Jedes Objekt hat (a) eine Höhe der Basis (ich nenne "Ebene") und (b) ein X / Y für die "Basis" oder "Fuß" von das Bild (Beispiele: Die Basis des Avatars liegt ihm zu Füßen; die Basis des Baumes befindet sich an den Wurzeln; die Basis des Flugzeugs befindet sich in der Mitte usw.) Dann sortiere ich einfach die niedrigste bis höchste Ebene, dann die niedrigste (höchste auf dem Bildschirm) bis zur höchsten Basis. Y, dann niedrigste (ganz links) bis höchste Basis-X. Dadurch werden die Kacheln so, wie man es erwarten würde.
Code zum Konvertieren von Bildschirm (Punkt) in Kachel (Zelle) und zurück:
quelle
Sie können den euklidischen Abstand vom höchsten und dem Betrachter am nächsten gelegenen Punkt verwenden, außer dass dies nicht ganz richtig ist. Dies führt zu einer sphärischen Sortierreihenfolge. Sie können dies korrigieren, indem Sie von weiter weg schauen. Weiter entfernt wird die Krümmung abgeflacht. Fügen Sie also einfach 1000 zu jeder der x-, y- und z-Komponenten hinzu, um x ', y' und z 'zu erhalten. Die Sortierung nach x '* x' + y '* y' + z '* z'.
quelle
Ein echtes Problem ist, wenn Sie einige Kacheln / Sprites zeichnen müssen, die zwei oder mehr andere Kacheln schneiden / überspannen.
Nach 2 (harten) Monaten persönlicher Problemanalyse habe ich endlich eine "korrekte Renderzeichnung" für mein neues cocos2d-js-Spiel gefunden und implementiert. Die Lösung besteht darin, für jede Kachel (anfällig) die Sprites zuzuordnen, die "vorne, hinten, oben und hinten" sind. Sobald Sie dies getan haben, können Sie sie nach einer "rekursiven Logik" zeichnen.
quelle