En m’intéressant de près à l’isométrie, je me suis aperçu que les méthodes pronées par Jobe Makar (Flash MX Games Design Demystified) et consorts au sujet du z-sorting n’étaient pas du tout adaptées pour un moteur 3D isométrique dont l’objectif final serait d’afficher des animations.
Je vous propose de partager aujourd’hui la solution que j’utilise. Elle vous permettra de gérer les profondeurs sans bug d’affichage dans un moteur 3d isométrique animé.
Le concept récurrent pour gérer la profondeur d’un objet dans un tileworld isométrique est d’assigner un z-sorting incrémenté de gauche à droite sur l’axe des x, puis de bas en haut sur l’axe des y comme indiqué sur le schéma ci-dessous :

Ce système fonctionne à merveille tant que l’on se contente du fait que chaque objet se trouvant à une position (x,y) se déplacera sur une case voisine d’un seul jet, sans interpolation de mouvement, autrement dit sans se trouver à un instant t à cheval entre deux cases.
Pourquoi me direz vous ?
Considérons l’exemple ci-dessous :

Un personnage se trouvant à la position 1,1 et voulant se rendre à la position 1,0 va devoir choisir son camp. S’il garde 4 comme profondeur le temps de l’animation pour se rendre sur la case destination, il va passer devant l’objet qui se trouve en 2,0.
S’il choisit de prendre directement sa profondeur d’arrivée (1), il sera le temps de son trajet affiché derrière l’objet se trouvant en 2,0.

On est confronté au même probléme dans le sens inverse comme vous pouvez le remarquer :

La plupart des moteurs utilisant ce système réussissent à tricher en jouant sur la taille des objets à l’intérieur des cases et sur l’instant ou la valeur z-sorting de l’objet en mouvement est modifiée. Mais ces solutions au bout du compte ne sont vraiment pas satisfaisantes pour gérer l’affichage de façon propre et logique.
D’où l’idée d’opter pour une organisation comme celle-ci, avec un z-sorting incrémenté en diagonales :

Cette fois-ci les animations sur l’axe des y peuvent-être gérées sans bug d’affichage :

Mais les esprits judicieux auront remarqué que le probléme est maintenant répercuté sur l’axe des x :

Sans plus attendre, voici la solution finale, le même tableau mais avec des intervalles en dizaine :

Hum … Quoi de mieux me direz-vous ?
L’idée est d’incrémenter de 15 la profondeur d’un personnage voulant se déplacer vers la droite sur l’axe des x (50 dans l’exemple devient 65) et de lui donner à la fin de son parcours la profondeur de la case d’arrivée (80 dans l’exemple ci-dessous) :

Même chose dans l’autre sens, on enléve 15 à la profondeur d’un personnage voulant se déplacer vers la gauche sur l’axe des x (50 devenant 35 dans le cas précis) et on lui attribue à la fin de son trajet la profondeur de la case destination (il passe donc de 35 à 20 en profondeur une fois arrivé) :

Dernier point, quelle méthode utiliser pour calculer la profondeur d’un objet en connaissant la largeur et la hauteur de la grille ainsi que sa position x et y ?
C’était le sujet d’un précédent thread, et je remercie Didier d’avoir trouvé une solution très élégante et rapide pour gérer cette problématique.
Voici le code que j’utilise :
private function _sum(n:Number) : Number { return (n * (n + 1) / 2); } public function calculDepth(x:Number, y:Number) { var r:Number = _sum(x + y) + x + 1; r = ((x + y) > (grid.x-1)) ? r -= _sum(x + y - (grid.x-1)) : r; r = ((x + y) > grid.y) ? r -= _sum(x + y - grid.y) : r; return (r*10); }
Voila, j’espère que le concept que j’ai développé et utilise couramment pourra contribuer à remplir un peu le vide auquel je me suis confronté lors de mes investigations sur le sujet.
Je tiens à remercier tout particulièrement Joan pour ses idées et Didier pour son algorithme de calcul remarquable ainsi que Jean-Louis pour la conversion en AS.
Comme d’habitude, vos questions, commentaires ou critiques sont les bienvenue.
Tu sais ce qui aurait été génial dans ton post ? C’est de rajouter une schema ISO a coté de chaque schéma à plat …
Je n’ai pas encore décortiqué ton raisonnement, mais je vais m’y pencher trés minutieusement, car je m’interesse pas mal a la 3D iso en ce moment …
Cette solution convient-elle aussi pour des affichages sur plusieurs niveaux (un immeuble dont il manque les murs par exemple) ?
Encore une autre question, avec le systèmes des profondeurs multiples de 10, on ne touche pas la profondeur pour un déplacement sur l’axe des Y c’est ca ? Et pour les déplacements en diagonales (même si je sais que tu n’en utilises pas pour l’instant), faut-il gérer les profondeurs comme si ca ne se déplacait que sur les X ?
Merci d’avance pour tes précisions, a+ !
Posted by LAlex | 12 octobre 2003, 14 h 12 minJe me suis intéressé pas mal à l’isométrie il y a quelques mois et je dois m’y remettre bientôt. Merci ton post sera très utile!
Mais comme dit Lalex, un schéma ISO aiderait beaucoup à visualiser le concept, je n’ai pas étudié à fond non plus, mais à première lecture je n’ai pas tout bien comprit, difficulté à visualiser certains trucs…
Posted by stef | 12 octobre 2003, 18 h 32 minMerci pour vos suggestions, je rajouterai des screens dans les jours qui viennent
Sinon pour gérer les étages j’utilise tout simplement un MC container avec un tileword à l’intérieur pour chaque niveau, l’étage le plus haut ayant le z-sorting le plus haut.
Ce système par contre ne permet pas de gérer une animation d’un objet transitant d’un étage à l’autre.
Quand aux déplacements en diagonales, avec le système que je préconise, ça fonctionne de manière quasi-identique avec un offset de 25.
Pour un personnage se trouvant en 1,1 :
- Pour aller en 0,0 : il faut lui enlever 25 de profondeur avant son déplacement et à la fin du trajet lui donner la valeur de la case d’arrivée.
- Pour aller en 2,2 : il faut lui ajouter 25 de profondeur avant son déplacement et à la fin du trajet lui donner la valeur de la case d’arrivée.
- Modifier la valeur juste à l’arrivée pour aller en 0,2 ou 2,0.
Posted by Francis Bourre | 12 octobre 2003, 22 h 42 minEn tout cas, c’est super sympa de partager tes connaissances sur le sujet !
J’attends avec impatience ton illustration en ISO !!!
Posted by LAlex | 13 octobre 2003, 10 h 04 minAh ben maintenant je comprends le pourquoi du comment du truc qu’on se demandais tous à quoi ça peut donc servir de remplir une matrice en diagonale
Bravo
Je communique le lien de cette page à Didier ça lui fera plaisir
Posted by JL | 17 octobre 2003, 13 h 39 minYo petepx,
c’est la première fois que je poste sur ce blog et avant toute chose, je te remercie sincèrement pour tous ces articles que tu partages ! c’est très enrichissant !
Je suis tombé sur ton thread dans FF concernant une fonction qui permettrait de déterminer les profondeur automatiquement, j’en ai fait une que j’ai posté là :
http://flash.media-box.net/viewtopic.php?p=215559#215559
Bonne continuation
Posted by Foxy | 8 juin 2004, 23 h 51 min