mercredi 24 mars 2010

Affichage d'une map 2D isométrique

Pour mon premier article, je vais parler de l'affichage isométrique dans le cadre d'un jeu 2D.

Les outils utilisés:
- Editeur: Visual Studio 2008
- Framework: XNA 3.1

J'utilise donc XNA qui permet le développement de manière simple des jeux vidéo. Ne vous inquiétez pas, mes explications peuvent être réutilisé avec d'autres langages et bibliothèques, il va juste falloir faire un peu de traduction :p.

Contexte

Pour créer une carte en 2D isométrique, vous devez imaginer un rectangle quadrillé, auquel on a appliqué une rotation de 45° degrés et réduit de moitié verticalement. Chaque case ( en forme de losange ) est appelée "tile" ( tuile en français ).

Définition d'une classe Tile


Ma classe Tile va comporter 2 attributs. Le premier est la texture de la tile ( de l'herbe, du sable ... etc.), le deuxième attribut est un vecteur2D qui va comporter les coordonnées de la tile.


class Tile
{
// Attributs
Texture2D texture;
Vector2 coordonnees;

public Tile()
{
this.texture = null;
this.coordonnees = Vector2.Zero;
}

public Tile(Texture2D texture, Vector2 cords)
{
this.texture = texture;
this.coordonnees = cords
}

public Texture2D Texture
{
get { return this.texture; }
set { this.texture = value; }
}
public Vector2 Coordonnees
{
get { return this.coordonnees; }
set { this.coordonnes = value; }
}
}


Création d'une map isométrique

Pour créer une map ( carte en français ) il va donc falloir assembler nos tiles de manière à avoir un losange. Etant donné que l'on a effectué une rotation de 45°, notre origine sera le côté haut de la map.

Ainsi pour se déplacer le long du vecteur X, on partira de haut à droite, et pour aller le long du vecteur Y, de haut à gauche.


Pour stocker nos tiles et ainsi créer notre map, nous allons faire un tableau à 2 dimensions de tile. Nous allons également initialiser une texture.


Tile[,] map = new Tile[longueur,largeur];
Texture2D tile = Content.Load("matile");


où longueur et largeur représente le nombre de tile composant la map.

Affichage

Pour afficher notre map, nous allons d'abord créer les boucles pour parcourir notre tableau de tile. Pour cela nous devons imbriquer une boucle for dans une autre. Nous allons boucler de 0 à la taille de la map, pour se faire on utilise la méthode GetLength qui renvoi la longueur de la dimension passé en paramètre.

Ensuite, on défini une variable row qui permet de créer une nouvelle ligne de tile quand on a fini la précédente.

Enfin on initialise un vecteur position qui va permettre de positionner les tiles pour les afficher.


// Indice servant à dessiner une ligne de tile
int row = 1;

// On affiche la carte à partir de (0,0)
Vector2 position = new Vector2(0.0f, 0.0f);

// On affichage d'abord la longueur
for (int l = 0; l < map.GetLength(0); l++)
{
// Puis la largeur de la map
for (int h = 0; h < map.GetLength(1); h++)
{
}
}


Bien, passons maintenant à l'affichage. Avec XNA, pour afficher des images 2D, nous devons dessiner à l'intérieur d'une spriteBatch, nous allons donc délimiter nos 2 boucles comme ceci, puis rajouter la ligne qui permet de dessiner la tile courante


// Indice servant à dessiner une ligne de tile
int row = 1;

// On affiche la carte à partir de (0,0)
Vector2 position = new Vector2(0.0f, 0.0f);

s
// On affichage d'abord la longueur
spriteBatch.Begin();
for (int l = 0; l < map.GetLength(0); l++)
{
// Puis la largeur de la map
for (int h = 0; h < map.GetLength(1); h++)
{
map[l, h] = new Tile(tile, position);
spriteBatch.Draw(map[l, h].Texture, map[l, h].Coordonnees, Color.White);
}
}
spriteBatch.End();


Pas bien compliquer non ? On créer d'abord une tile que l'on place dans le tableau map, puis avec la méthode Draw(), on affiche la tile avec sa texture et ses coordonnées.

Positionner les tiles pour l'affichage

Maintenant la partie la plus délicate, est l'incrémentation de la position. Notre origine est la tile tout en haut. Pour afficher la première ligne, nous allons nous déplacer vers la droite, en se décalant d'une moitié de longueur de tile sur l'axe X et une moitié de largeur sur l'axe Y. Comme un escalier !

Ensuite, on va devoir revenir à la tile d'origine, se décaler d'abord d'un cran à gauche avant de refaire l'opération. C'est aussi ici que va sortir la variable row.

Voici donc l'affichage isométrique avec les positions incrémentés


// Indice servant à dessiner une ligne de tile
int row = 1;

// On affiche la carte à partir de (0,0)
Vector2 position = new Vector2(0.0f, 0.0f);

// On affichage d'abord la longueur
for (int l = 0; l < map.GetLength(0); l++)
{
// Puis la largeur de la map
for (int h = 0; h < map.GetLength(1); h++)
{
map[l, h] = new Tile(tile, position);
spriteBatch.Draw(map[l, h].Texture, map[l, h].Coordonnees, Color.White);
// On incrémente la position pour la prochaine tile
position.X += tile.Width / 2;
position.Y += (tile.Height / 2);
}
// Une fois la première ligne faite, on retourne à la case départ,
// et on calcule la position de la ligne suivante
position.X = - tile.Width / 2 * row;
position.Y = (tile.Height - 6) / 2 * row;
row++;
}


Voilà, vous devriez normalement avoir un affichage isométrique comme sur le schéma au dessus. Le prochain article traitera des coordonnées, comment convertir les coordonnées de l'écran aux coordonnées isométriques de la carte.

J'espère que ce premier billet vous a plu, n'hésitez pas à faire des remarques ou si vous souhaitez plus de détail contacter moi !

1 commentaire: