IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

Coordonnées pour une map en 2D isométriques


Sujet :

Contribuez

  1. #1
    Yordarus
    Invité(e)
    Par défaut Coordonnées pour une map en 2D isométriques
    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.

    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; }
            }
        }
    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
     
    Tile[,] map = new Tile[longueur,largeur];
    Texture2D tile = Content.Load<Texture2D>("matile");
    Affichage isométrique

    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

    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();
    Coordonnées

    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.

    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));
            }
    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.

    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    float x =  Mouse.GetState().X + camera.Pos.X
    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 ).

    Ce qui donne au final

    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));
            }
    Conclusion

    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 !

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 39
    Points : 25
    Points
    25
    Par défaut
    Salut,

    Ton code fonctionne très bien, merci pour ca.

    Par contre, j'aimerai pouvoir faire l'inverse, à savoir, passer des coordonnées iso vers des coordonnées screen (pour placer des bâtiment), aurait ca sous la main stp ?

    Merci

  3. #3
    Membre régulier Avatar de Othana
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2007
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2007
    Messages : 188
    Points : 86
    Points
    86
    Par défaut
    Bonjour ici.

    Avec un autre membre, on est en train de travailler sur un projet similaire.
    Mais à nous va se poser 2 problèmes supplémentaires :
    - la "hauteur", car nous comptons faire usage des niveaux en hauteur (monter descendre gauche droite haut bas...)
    - la rotation de l'écran !!! ou plutôt, de la map. Elle devra pouvoir pivoter de 90° (pour l'instant), tout en conservant les coordonnées relatives des objets placés, recalculer les coordonnées d'écran...

    Nous en sommes encore qu'à la phase d'analyse et conception, donc nous lisons avec beaucoup d'attention les différents sujets ici.

    Toutefois, nous aurions besoin d'encore pas mal de conseil sur ces deux points.
    Merci aux connaisseurs de prendre contact avec moi et/ou d'en discuter ici (ou ouvrir un nouveau sujet, s'il faut).

  4. #4
    Membre expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Points : 3 295
    Points
    3 295
    Billets dans le blog
    1
    Par défaut
    salut,

    pour la gestion plus générique des choses, faut passer à l'idée de l'inversion de matrice et de faire du picking...

    faire de la 3d iso avec rotation(s) libre(s) c'est alors de la 3d normale...

    y a juste la matrice de visualisation qui change, les matrices d'homothétie (position + échelle + rotations) sont les mêmes en fait...

    si tu fais tourner ta map alors tu devras avoir tes objets définis sous autan d'angles que nécessaire... voir avoir un vrai maillage complet plutôt que des sprites en rotations libres...
    soyons pensez à mettre quand votre problème est résolu ou à utiliser pour les réponses pertinentes...
    ne posez pas de problématique soi-disant simplifiée sur des problèmes que vous n'êtes pas capable de résoudre par respect pour ceux qui planchent dessus... sinon: et à utiliser pour insérer votre code...

  5. #5
    Membre régulier Avatar de Othana
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2007
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2007
    Messages : 188
    Points : 86
    Points
    86
    Par défaut
    Oui, côté sprites, j'ai déjà pensé à ça. tout au moins pour les objets mobiles (perso, créatures...) qui auront un dessin pour chaque étape d'animation sur 5 angles (demi-étoile à 8 branches). Le reste fera l'objet d'un flip pour les autres directions. J'ai déjà travaillé sur un jeu en vue 2D iso, mais façon Zelda (il ne s'agit que d'un déplacement haut-bas-gauche-droite à l'écran, sur un fond ressemblant à de la 3D iso - aucune réelle prise en charge de hauteur de bloc).
    Quand je dis rotation à 90°, j'entends bien rester dans un environnement isométrique, pas faire de la rotation de map comme dans un STR.

    Mais vu la complexité d'une telle 3D iso (voir le jeu Cadaver ou Landstalker pour un parfait exemple), j'ai peur que nous devions finalement passer à un modèle du genre Ragnarok Online. Sauf si je trouve le moyen de contacter GameLoft qui semble drôlement bien s'y connaitre (une chance que mon directeur a un contact chez eux).

  6. #6
    Membre expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Points : 3 295
    Points
    3 295
    Billets dans le blog
    1
    Par défaut
    le seul truc c'est de passer en revue les cases dans le bon ordre selon l'angle pour éviter les artéfacts ou lors des tests de picking si tu as des recouvrements...

    en as3 (flash), tu as juste à positionner tes objets, il génère automatiquement les masques de picking...

    une façon simple de tester si tu cliques sur l'objet ou pas c'est d'utiliser un masque correspondant à la projection de l'objet... tu traduis les coordonnées en local de la case et tu regardes la couleur au point trouvé... ça te dit immédiatement si tu es sur l'objet ou pas... y a juste à tester en respectant l'ordre de profondeur. pour les problèmes d'altitude l'ago devra prendre en compte la (ou les) cases du dessous s'il y a possibilité de cliquer sur un truc en hauteur
    soyons pensez à mettre quand votre problème est résolu ou à utiliser pour les réponses pertinentes...
    ne posez pas de problématique soi-disant simplifiée sur des problèmes que vous n'êtes pas capable de résoudre par respect pour ceux qui planchent dessus... sinon: et à utiliser pour insérer votre code...

Discussions similaires

  1. Equation pour une map en 3D isometrique?
    Par Zan dans le forum Interfaces Graphiques en Java
    Réponses: 1
    Dernier message: 11/06/2007, 05h09
  2. commentaire pour une map cliquable
    Par Boromus dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 20/02/2007, 09h51
  3. octree + VBO pour une map
    Par f56bre dans le forum OpenGL
    Réponses: 4
    Dernier message: 17/10/2006, 18h54
  4. coordonnées pour une infobulle
    Par leodi dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 12/03/2006, 17h21
  5. [Langage][Map] Quel langage pour une map
    Par Aldur dans le forum Général Conception Web
    Réponses: 1
    Dernier message: 23/12/2005, 11h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo