Bonsoir !
A la demande de Matt.M, je poste ici ma petite aventure lors du codage de mon petit jeu.
Tout d'abord, voici les technologies utilisées: XNA 3.1 ( C# ), Visual Studio 2008
Attention, le code est actuellement en mode bourrin. Je dois encore optimiser et ranger le code pour que ça soit plus clair, néanmoins c'est utilisable et compréhensible comme ça.
Contexte
Codant un jeu en 2D isométrique, je me suis confronté à un problème de conflit entre les coordonnées de ma map et la camera. Je vais d'abord vous expliquez comment j'affiche ma carte pour ensuite vous parlez des coordonnées.
Tout d'abord, j'ai une classe Tile ( case ) qui contient un Vector2 pour la position et une Texture2D pour la texture de la case.
Dans mon programme principal, j'ai un tableau de tile et une texture
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 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; } } }
Affichage isométrique
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 Tile[,] map = new Tile[longueur,largeur]; Texture2D tile = Content.Load<Texture2D>("matile");
Voici la manière dont je vais gérer ma carte. De haut à droite on a x, et de haut à gauche on a y.
Voici la manière dont je procède pour afficher ma carte en isométrie
Coordonnées
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 // 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 commence le bloc de dessin spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState, camera.get_transformation(graphics.GraphicsDevice)); // Tableau à 2 dimensions, donc boucle imbriquée // On affichage d'abord la longueur for (int l = 0; l < floor.GetLength(0); l++) { // Puis la largeur de la map for (int h = 0; h < floor.GetLength(1); h++) { // Je remplis mon tableau map et je dessine 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 // Je soustrais 4 car sur l'image de ma tile il y a une bordure de 4 pixel. Dans le cadre d'une tile "plate" on ne soustrait rien par exemple. position.X += tile.Width / 2; position.Y += (tile.Height / 2) - 4; } // 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++; } spriteBatch.End();
Ensuite, pour trouver où est mon curseur par rapport à la carte, je dois convertir la position de la souris à des coordonnées "isométriques". La fonction m'a été donné par le très sympathique Nouk² !
C'est ici que mon problème est apparu.
Ce code marche très bien à condition de ne pas bouger ma camera. En effet, en 2D il n'existe pas vraiment de camera, pour approcher ce concept, on va en faite "déplacer" la position de tous les éléments dans le sens inverse de la direction de la camera, ainsi si on veut regarder à gauche, on va déplacer la map à droite.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 private Vector2 ScreenToIso() { float x = Mouse.GetState().X; float y = Mouse.GetState().Y; Vector2 position; position.X = (float)Math.Floor((y / tilesand.Height) + (x / tilesand.Width)); position.Y = (float)Math.Ceiling((y / tilesand.Height) - (x / tilesand.Width)); }
Ma camera était à la position (0,0) et fixe le point central de mon écran. Je devais donc à chaque déplacement de camera, additionner de combien la camera s'est déplacée aux coordonnées de ma souris.
Donc
Hors comme je l'ai dis précédemment la camera fixe le point central de mon écran. Je dois donc soustraire la moitié de la hauteur et largeur de mon écran. Pour obtenir ces infos j'utilise Windows.ClientBounds.Width et Height avec XNA ).
Code : Sélectionner tout - Visualiser dans une fenêtre à part float x = Mouse.GetState().X + camera.Pos.X
Ce qui donne au final
Conclusion
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 private Vector2 ScreenToIso() { float x = (camera.Pos.X - Window.ClientBounds.Width / 2 ) + Mouse.GetState().X; float y = (camera.Pos.Y - Window.ClientBounds.Height / 2) + Mouse.GetState().Y; Vector2 position; position.X = (float)Math.Floor((y / tilesand.Height) + (x / tilesand.Width)); position.Y = (float)Math.Ceiling((y / tilesand.Height) - (x / tilesand.Width)); }
Ainsi, peut importe si je bouge la camera, j'arrive à obtenir la bonne case lorsque ma souris passe dessus. Et en utilisant mon tableau, j'ai juste à l'utiliser comme ceci pour accéder à l'élément Tile
map[position.X,position.Y].Texture;
Voilà, j'espère que ma petite aventure pourra vous aider, si vous avez des questions n'hésitez pas, j'essayerai d'y répondre au mieux.
Je commence doucement la création d'un jeu, et c'est une formidable expérience malgré les petits défauts de jeunesse niveau programmation.
Amusez vous bien !
Partager