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

Langage C++ Discussion :

std::map définissant une carte pour tilegame


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations forums :
    Inscription : Avril 2009
    Messages : 6
    Par défaut std::map définissant une carte pour tilegame
    Bonjour à tous ceux qui me liront,

    Je me suis mis, il y a quelque temps à la programmation d'un petit jeu en 2D utilisant SDL sous linux. Rien de bien sorcier, c'est surtout à des fin d'auto-formation. Afin de continuer dans cette optique je me suis dis que pour stocker ma carte j'allais utiliser les maps de la stl. C'est bien là que les choses se corsent. J'ai du mal à visualiser dans quelle direction partir. Je vais tout de suite passer dans le vif du sujet. Si vous voulez voir le reste du code vous pouvez le consulter ici : https://github.com/Shaihuld/Provas

    Voici le code source définissant ma carte :
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #ifndef MAP_H
    #define MAP_H
     
    #include <iostream>
    #include <map>
     
    #include "latlon.h"
    #include "latloncomp.h"
    #include "block.h"
     
    using namespace std;
     
    typedef map<LatLon,Block,LatLonComp> world;
     
    class Map{
    	private :
     
    	public:
    	world myworld;
    	world::iterator itr;
    	Map();
     
    };
    #endif
     
    --------
     
    // je peuple ma carte de cette façon :
     
    #include "map.h"
     
    Map::Map(){
    	int i,j;
     
    	for (i = 0; i<3;i++){
    		for (j=0; j<10; j++){
    			cout << "i :" << i << " j : " << j << endl;
    			myworld[LatLon(i,j)] = Block(2);
    		}
    	}
    	for (i = 3; i<10;i++){
    		for (j=10; j<15; j++){
    			cout << "i :" << i << " j : " << j << endl;
    			myworld[LatLon(i,j)] = Block(1);
    		}
    	}
    }
    les classes pour ma map :

    -latlon :
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #ifndef LATLON_H
    #define LATLON_H
    class LatLon {
     
    	private :
    	int x, y;
     
    	public:
    	LatLon(int, int);
     
    	//geters
    	int Get_x() const;
    	int Get_y() const;
     
    	//seters
    	void Set_x(int);
    	void Set_y(int);
     
    };
     
    #endif
     
    ---------
     
    #include "latlon.h" 
     
    LatLon::LatLon(int i, int j){
    	x = i;
    	y = j;
    }
     
    int
    LatLon::Get_x() const{
    	return x;
    }
     
    int
    LatLon::Get_y() const{
    	return y;
    }
     
    void
    LatLon::Set_x(int xp){
    	x = xp;
    }
     
    void
    LatLon::Set_y(int yp){
    	y = yp;
    }
    -mon objet de comparaison :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #ifndef LATLONCOMP_H
    #define LATLONCOMP_H
     
    class LatLonComp {
    	public:
    		bool operator() (LatLon a, LatLon b) {
    			if (a.Get_x() == b.Get_x()) return a.Get_y()< b.Get_y() ;
    			if (a.Get_y() == b.Get_y()) return a.Get_x()< b.Get_x() ;
    		}
    };
     
    #endif
    -et mon block (j'ai plusieurs constructeurs pour savoir si ça ne venait pas du fait que ce soit un appel à un ctor de copy ou quelque chose comme ça qui provoquait mon problème):
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #ifndef BLOCK_H
    #define BLOCK_H
     
     class Block {
     
    	private :
     
    	public:
    	int t;
     
    	Block();
    	Block(int);
    	Block(const Block& p);
    	Block &  operator= (const Block & b);
     
    };
     
     
     
    #endif
     
    --------
     
    #include "block.h"
    #include <iostream>
     
    using namespace std;
    Block::Block(){
    	t=0;
    }
     
    Block::Block(int a){
    	t=a;
    }
     
     
    Block::Block(const Block& b) {
        t = 4;
    	cout << "copy ctor" << endl;
    }
     
    Block & Block::operator= (const Block & b)
    {
      Block::t=b.t;
    cout << "operator = " << endl;
      return *this;
    }

    voilà ma fonction qui va gérer l'affichage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void
    Display::blit_map(Map& w, int tw, int th){
    	SDL_Rect p;
    	for(w.itr = w.myworld.begin() ; w.itr != w.myworld.end() ; ++w.itr){
    		p.x =(*w.itr).first.Get_x()*tw;
    		p.y = (*w.itr).first.Get_x()*th;
    		if ((*w.itr).second.t == 2){
    			blit_image("watter.bmp", p, 0);
    		}
    		else {
    			blit_image("error.bmp", p, 0);
    		}
    	}
    }
    cependant rien n'a l'air de bien vouloir apparaitre

    Alors j'espère que je ne suis pas totalement hors sujet en postant celà ici.

    J'aimerai comprendre ce que je ne fais pas correctement dans ma map qui fait que l'affichage ne fonctionne pas.
    Aussi je me demande si la méthode que j'utilise est correcte pour ce que je veux faire.
    Pour finir, comment repartir de la position centrale de mon futur personnage vers la liste des blocks à afficher (j'ai encore un peu de temps pour ça ).

    Si vous désirez plus d'informations n'hésitez pas. Si vous voulez que je clarifie quelque chose aussi dites moi ! Je suis un peu dans mon truc donc ça me semble clair et il se peut que je ne traduise pas exactement ce que je veux dire.

    Merci de m'avoir lu et de votre aide.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Pour commencer, ta fonction d'ordre (LatLongComp) n'est pas totale : par exemple si on a deux objects de type LatLongComp a { x = 5, y = 3 } et b { x = 3, y = 5 }, lequel des deux est le "plus petit" (au sens de cette relation d'ordre ) ?
    D'autre part pourquoi utiliser une map et pas un std::vector ?

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations forums :
    Inscription : Avril 2009
    Messages : 6
    Par défaut
    Joe,

    En effet la comparaison est incomplète. D'un autre côté, je n'ai pas vraiment d'explication sur pourquoi j'ai plutôt utilisé map que vector. std::map pour faire une map m'a semblé logique ...

  4. #4
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut
    Bonjour,

    Citation Envoyé par Shaihuld Voir le message
    Joe,

    En effet la comparaison est incomplète. D'un autre côté, je n'ai pas vraiment d'explication sur pourquoi j'ai plutôt utilisé map que vector. std::map pour faire une map m'a semblé logique ...
    Ca te permet d'indexer en fonction de LatLon pour retrouver rapidement un Block en fonction de LatLon. Avec un std::vector, tu devrais parcours séquentiellement le vecteur.

    Pour ton opérateur LatLonComp, je pense que la chose suivante fait l'affaire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #ifndef LATLONCOMP_H
    #define LATLONCOMP_H
     
    class LatLonComp {
    	public:
    		bool operator() (LatLon const & a, LatLon const & b) {
    			return ( a.Get_x() < b.Get_x() )
    			    || ( a.Get_x() == b.Get_x() && a.Get_y()< b.Get_y() );
    		}
    };
     
    #endif

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,
    Citation Envoyé par Shaihuld Voir le message
    Joe,

    En effet la comparaison est incomplète. D'un autre côté, je n'ai pas vraiment d'explication sur pourquoi j'ai plutôt utilisé map que vector. std::map pour faire une map m'a semblé logique ...
    Mais, dans quelle mesure ne veux tu pas, en réalité, créer une matrice de tiles

    Je m'explique...:

    en gros, et bien que n'ayant regardé le code que d'un oeil () tu veux créer un "monde 2D" qui est composé d'une série de tuiles qui prennent place sur une "grille".

    Si tu estimes que les coordonées horizontales correspondent à la lattitude et que les coordonnée verticales correspondent à la longitude, tu peux parfaitement te contenter d'un tableau de tuiles et utiliser la fameuse formule tuile[longitude][lattitude] = monde[ longitude * lattitudeMax + lattitude]

    En effet, il faut savoir que l'accès aux éléments d'une map est, d'office, itératif ... : Si tu n'essaye pas d'accéder à l'élément qui sert effectivement de racine à l'arbre primaire ( qui n'est pas, soit dit en passant, l'élément que tu obtiens avec la fonction membre first() ), tu devra d'office parcourir "plusieurs éléments" pour arriver à trouver celui qui t'intéresse.

    Par contre, en utilisant un tableau (éventuellement à une seule dimension grace à la formule que j'ai donné) tu peux accéder à n'importe quel élément de ta carte en temps constant : cela te prendra exactement le temps d'un déplacement pour accéder à la tuile[0][0] que pour accéder à la tuile[124][180]

    Et comme tu feras excessivement peu de recherche mais beaucoup d'accès, le choix d'une collection permettant l'accès au membre en temps constant s'avérera, du point de vue des performances, très largement plus intéressant

    Ceci dit, je comprend ta logique, mais c'est sans oublier que le terme anglais map représente en réalité deux choses :

    en anglais courent, map, c'est une carte, et je présumes que c'est ce qui t'a fait pencher vers ce conteneur particulier

    Mais, en informatique, une map est une collection qui fait... un mapping qui pourrait plus ou moins signifier "association" : qui met en relation une clé (ta structure LatLon ) et une valeur (ta structure Block ) et qui permet de retrouver (ce qui signifie surtout : de rechercher ) la valeur associée à une clé identifiant un objet de manière unique.

    Le fait est que tu n'as, a priori, pas besoin de rechercher tes différentes tuiles, dés le moment où tu sais combien il y en a en vertical et combien il y en a en horizontal : si tu es sur une la tuile[x][y], tu sais que celle qui se trouve à gauche est la tuile[x][y-1], que celle qui se trouve à droit est la tuile [x][y+1] et que celle qui se trouve au dessus est la tuile[x-1][y]...

    Autant essayer d'accéder en temps constant à ces tuiles si tu en as l'occasion
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Je confirme que le choix d'une map pour gérer ça semble assez malheureux. Le seul cas où je pourrait utiliser une map avec des coordonnées de cellules comme clef serait si la plupart des cellules sont vides (où dans un même état), une map permettrait alors de ne stocker que les cellules pleines, et d'économiser alors de la mémoire. Sinon, tant que la taille de la zone à gérer reste raisonnable, un simple vector devrait être plus intéressant.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations forums :
    Inscription : Avril 2009
    Messages : 6
    Par défaut
    Merci à tous,

    J'ai utilisé map car j'avais envie d'apprendre à m'en servir, je ne m'en était jamais servi avant (de même que vector cependant). Au vu de toutes les explications je vois maintenant que le choix n'a pas été judicieux pour résoudre ce problème particulier (stocker mes tiles).

    Je vais donc changer ça Merci beaucoup pour vos réponses

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Choix d'une carte pour linux embarqué
    Par neroz dans le forum Linux
    Réponses: 0
    Dernier message: 17/01/2013, 17h58
  2. Quelle taille choisir pour une carte Google Maps sur site mobile?
    Par Adélaide dans le forum Webdesign & Ergonomie
    Réponses: 2
    Dernier message: 30/04/2010, 09h34
  3. [MAPPING] map avec une liste pour valeur
    Par djodjo dans le forum Hibernate
    Réponses: 0
    Dernier message: 11/03/2010, 18h39
  4. prédicat pour min_element d'une std::map
    Par Kurisu dans le forum SL & STL
    Réponses: 6
    Dernier message: 11/09/2006, 19h27
  5. [Images] représentation d'une carte pour jeu en php
    Par maniaco_jazz dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 29/11/2005, 10h41

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