Vous êtes ici : Accueil - Ressources Flash - 3D Isométrie et dénivélation.
Après avoir pas mal triturer la 3D isométrique dans mon dernier projet, je vais essayer de me lancer dans ce tutoriel pour montrer que ce n'est pas si difficile que cela à concevoir. Tout va reposer sur un peu de trigonométrie.
Pour commencer, il est important de noter que le terme 3D isométrique est abusiment utilisé pour nommer tous les moteurs de rendu isométrique. La plupart des moteurs en Flash n'utilise que 2 dimensions. C'est donc de la fausse 3D isométrique et il serait plus logique d'appeler ce rendu 2D isométrique.
Pour définir le principe, c'est une méthode de représentation en perspective où tout les axes ont la même importance. De ce fait, contrairement à la vraie 3D, les calculs sont très simplifiés.
Lorsque l'on restreint encore plus les spécifications de ce rendu, chose que l'on va faire dans ce tutoriel, on peut arriver à un stricte minimum nécessaire. En l'occurence, tout ce qui a attrait à la rotation d'objet dans l'espace, à l'éclairage (raycasting) sera laissé de côté. Cela permet d'introduire beaucoup d'astuces, comme la réalisation graphique d'une seul face par élément qui restera toujours visible, un mapping sur 2 dimensions, la notion de dénivélation qui simulera le troisième repère dans l'espace .
On va se basé sur une petite map 4x4 :

La projection sur le plan isométrique des cases de cette grille à 2 dimensions va se schématiser par une rotation de 90° d'un vecteur unitaire. Je n'entrerais pas dans les détails, il y a assez de documentions sur le net, je pense. Il suffit juste de garder en mémoire ces deux équations :
// Rotation isométrique
pos x isométrique = numéro de ligne + numéro de colonne
pos y isométrique = numéro de ligne - numéro de colonne
Après rotation, nous optenons cette grille :
Cette simple opération nous permet d'avoir une "vue de dessus". Il est nécessaire ensuite de mettre à l'échelle la représentation graphique de ce que l'on a à l'écran. En isométrie, on parle d'angle de vue. L'angle le plus utilisé est celui de 20°. C'est celui que j'ai utilisé dans ce tutoriel. Avec un peu de trigonométrie, on peut calculer les valeurs des diagonales d'une case, mais cela rajoute en calcul et il est plus simple de les définir en terme de constante, étant donné que le but du jeu est avant tout de simplifier le rendu :
// Angle de vue à 20° (pseudo code)
echelle hauteur = diagonale verticale / 2
echelle largeur = diagonale horizontale / 2
// projection isométrique et mise à l'échelle
var _ech = { w : 32, h : 11.66 }; // échelle utilisée
var _map = { col : 4, row = 4 }; // taille de la map
for ( var i=1; i<=4; i++) { // axe des y
for ( var j=1; j <=4; j++) { // axe des x
var numCase = ( i-1 )*_map.col + j;
grille[ "case"+numCase ].xPos = (i + j)*_ech.w;
grille[ "case"+numCase ].yPos = (i - j)*_ech.h;
}
}
Graphiquement, cela donne ceci :

L'étape suivante va consister à rendre l'effet de profondeur dans Flash, ce qui permet de faire passer des objets par dessus d'autres. C'est ce que l'on appelle le zSorting. A ce propos, je renvoie à l'excelent article de Petepx sur son blog (en espérant qu'il reste assez longtemps sur ce lien), donc je ne reviendrait pas dessus. Pour ma part, j'utilise la fonction donnée par Foxy qui est en AS1. (Celle de Petepx est en AS2) .
Edit : avec les différentes migrations de serveurs de mediabox, l’ancien post se trouve ici :
http://flash.mediabox.fr/index.php?showtopic=17453&view=findpost&p=143009 (prendre la solution donnée par Petepx, message n°8)
Après calcul du zSorting de chaque case, on obtient les profondeurs suivantes :

Dernière étape : la notion de dénivélation. La méthode la plus simple est d'utiliser un coefficient multiplicateur qui va rajouter une valeur sur la propriété _y d'une case.
// fonction de zSorting
function zSorting ( x, y, tx, ty ) {
var s = x+y, r = s * ( s + 1 ) / 2 + x + 1;
s > tx - 1 ? r -= ( ( s-tx+1 )*( s-tx+2 ) )/2 : null;
s > ty ? r -= ( ( s-ty )*( s-ty+1 ) )/2 : null;
return r;
}
// projection isométrique, mise à l'échelle et dénivélation
var _ech = { w : 32, h : 11.66 }; // échelle utilisée
var _map = { col : 4, row = 4 }; // taille de la map
var _coeffDeniv = 8; // coefficient de dénivélation
for ( var i=1; i<=_map.col; i++) { // axe des y
for ( var j=1; j <=_map.col; j++) { // axe des x
var numCase = ( i-1 )*_map.col + j;
var case = grille[ "case"+numCase ];
case.xPos = (i + j)*_ech.w;
case.yPos = (i - j)*_ech.h + case.deniv*_coeffDeniv;
case.zSort = zSorting( j, i, _map.col, _map.row );
}
}
Et un petit exemple de ce que cela peut donner :
Dans un autre article, j'essaierais d'inclure le concept de plusieurs niveaux pour simuler des passages en dessous de certaines cases et bien sur une méthode de stockage des données de map.