Mise à jour: algorithme de rendu de carte corrigé, ajout d'illustrations supplémentaires, mise en forme modifiée.
Peut-être que l'avantage de la technique "zig-zag" pour mapper les tuiles à l'écran peut être dit que les tuiles x
et les y
coordonnées sont sur les axes vertical et horizontal.
Approche "Dessin dans un diamant":
En dessinant une carte isométrique à l'aide de "dessin dans un losange", qui, je crois, se réfère simplement au rendu de la carte en utilisant une for
boucle imbriquée sur le tableau à deux dimensions, comme cet exemple:
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)
)
Avantage:
L'avantage de l'approche est qu'il s'agit d'une simple for
boucle imbriquée avec une logique assez simple qui fonctionne de manière cohérente dans toutes les tuiles.
Désavantage:
Un inconvénient de cette approche est que les coordonnées x
et y
des tuiles sur la carte augmenteront en diagonales, ce qui pourrait rendre plus difficile la cartographie visuelle de l'emplacement à l'écran sur la carte représentée sous forme de tableau:
Cependant, il va y avoir un piège à l'implémentation de l'exemple de code ci-dessus - l'ordre de rendu provoquera le dessin des tuiles censées être derrière certaines tuiles au-dessus des tuiles en face:
Afin de corriger ce problème, l'ordre de la for
boucle interne doit être inversé - en commençant par la valeur la plus élevée et en effectuant un rendu vers la valeur inférieure:
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)
)
Avec le correctif ci-dessus, le rendu de la carte doit être corrigé:
Approche "zig-zag":
Avantage:
L'avantage de l'approche "zig-zag" est peut-être que la carte rendue peut sembler un peu plus compacte verticalement que l'approche "diamant":
Désavantage:
En essayant d'implémenter la technique du zig-zag, l'inconvénient peut être qu'il est un peu plus difficile d'écrire le code de rendu car il ne peut pas être écrit aussi simple qu'une for
boucle imbriquée sur chaque élément d'un tableau:
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
)
En outre, il peut être un peu difficile d'essayer de déterminer la coordonnée d'une tuile en raison de la nature décalée de l'ordre de rendu:
Remarque: Les illustrations incluses dans cette réponse ont été créées avec une implémentation Java du code de rendu de tuiles présenté, avec le int
tableau suivant comme carte:
tileMap = new int[][] {
{0, 1, 2, 3},
{3, 2, 1, 0},
{0, 0, 1, 1},
{2, 2, 3, 3}
};
Les images de tuiles sont:
tileImage[0] ->
Une boîte avec une boîte à l'intérieur.
tileImage[1] ->
Une boîte noire.
tileImage[2] ->
Une boîte blanche.
tileImage[3] ->
Une boîte avec un grand objet gris dedans.
Remarque sur la largeur et la hauteur des carreaux
Les variables tile_width
et tile_height
qui sont utilisées dans les exemples de code ci-dessus font référence à la largeur et à la hauteur de la tuile au sol dans l'image représentant la tuile:
L'utilisation des dimensions de l'image fonctionnera, tant que les dimensions de l'image et les dimensions de la tuile correspondent. Sinon, la carte de tuiles pourrait être rendue avec des espaces entre les tuiles.
j = (2 * x - 4 * y) / tilewidth * 0.5; i = (p.x * 2 / tilewidth) - j;
.Dans les deux cas, le travail est fait. Je suppose que par zigzag vous voulez dire quelque chose comme ceci: (les nombres sont dans l'ordre de rendu)
Et par diamant, vous entendez:
La première méthode nécessite plus de tuiles rendues pour que le plein écran soit dessiné, mais vous pouvez facilement vérifier les limites et ignorer toutes les tuiles complètement hors de l'écran. Les deux méthodes nécessiteront un certain nombre de calculs pour savoir quel est l'emplacement de la tuile 01. En fin de compte, les deux méthodes sont à peu près égales en termes de mathématiques requises pour un certain niveau d'efficacité.
la source
Si vous avez des carreaux qui dépassent les limites de votre diamant, je vous recommande de dessiner dans l'ordre de la profondeur:
la source
La réponse de Coobird est la bonne et complète. Cependant, j'ai combiné ses conseils avec ceux d'un autre site pour créer du code qui fonctionne dans mon application (iOS / Objective-C), que je voulais partager avec tous ceux qui viennent ici à la recherche d'une telle chose. S'il vous plaît, si vous aimez / votez pour cette réponse, faites de même pour les originaux; tout ce que j'ai fait, c'est de «me tenir sur les épaules de géants».
Quant à l'ordre de tri, ma technique est un algorithme de peintre modifié: chaque objet a (a) une altitude de la base (j'appelle "niveau") et (b) un X / Y pour la "base" ou "pied" de l'image (exemples: la base de l'avatar est à ses pieds; la base de l'arbre est à ses racines; la base de l'avion est l'image centrale, etc.) Ensuite, je trie simplement le niveau le plus bas au niveau le plus élevé, puis le plus bas (le plus haut à l'écran) à la base la plus élevée- Y, puis le plus bas (le plus à gauche) au plus haut base-X. Cela rend les tuiles comme on pourrait s'y attendre.
Code pour convertir l'écran (point) en tuile (cellule) et inversement:
la source
Vous pouvez utiliser la distance euclidienne du point le plus élevé et le plus proche du spectateur, sauf que ce n'est pas tout à fait correct. Il en résulte un ordre de tri sphérique. Vous pouvez redresser cela en regardant de plus loin. Plus loin, la courbure s'aplatit. Donc, ajoutez simplement, disons, 1000 à chacun des composants x, y et z pour donner x ', y' et z '. Le tri sur x '* x' + y '* y' + z '* z'.
la source
Le vrai problème est lorsque vous devez dessiner des tuiles / sprites qui se croisent / s'étendent sur deux autres tuiles ou plus.
Après 2 mois (difficiles) d'analyses personnelles des problèmes, j'ai finalement trouvé et implémenté un "dessin de rendu correct" pour mon nouveau jeu cocos2d-js. La solution consiste à cartographier, pour chaque tuile (sensible), quels sprites sont "avant, arrière, haut et derrière". Une fois cela fait, vous pouvez les dessiner en suivant une "logique récursive".
la source