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

Qt Discussion :

Un jeu de snake en 2D et tile mapping


Sujet :

Qt

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 20
    Par défaut Un jeu de snake en 2D et tile mapping
    Bonjour a tous,

    J'ai un projet a réaliser qui consiste a recoder le celebre jeu Snake en C++, avec pour GUI Qt.
    Le 'core' de mon programme est deja code, il me transmet en parametre un tableau en deux dimensions d'entiers contenant des entiers (oh really? ) allant de 0 a 7, chaque entier correspondant a un element du jeu (0 = vide, 1 = mur, 2 = queue du serpent, 3 = corps, 4 = tete et 7 = pomme).

    Le tableau de depart est celui ci :

    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
    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 2 3 3 4 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    Mon problème est le suivant :
    je souhaite pouvoir parcourir ce tableau d'entiers en affichant a chaque valeur rencontrée (0,1,2,3 ...) l'image qui lui correspond. J'ai déjà essaye et réussi a le faire en utilisant QGraphicsScenem QGraphicsView et QGraphicsItem.
    L'affichage est le suivant :


    Voila le code d’implémentation des images :

    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
    51
      QGraphicsItem *item;
      QPixmap image;
      int   width = 0;
      int   heigth = 0;
     
      for (int i = 0; i < size; i++)
        {
          for (int j = 0; j < size; j++)
            {
              if (tab[i][j] == 1)
                {
                  image.load("./res/mur.png", 0, Qt::AutoColor);
                  item = scene->addPixmap(image);
                  item->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 4)
                {
                  image.load("./res/tete.png", 0, Qt::AutoColor);
                  item = scene->addPixmap(image);
                  item->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 2)
                {
                  image.load("./res/queue.png", 0, Qt::AutoColor);
                  item = scene->addPixmap(image);
                  item->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 3)
                {
                  image.load("./res/corps.png", 0, Qt::AutoColor);
                  item = scene->addPixmap(image);
                  item->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 7)
                {
                  image.load("./res/apple.jpg", 0, Qt::AutoColor);
                  item = scene->addPixmap(image);
                  item->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 0)
                width += 20;
            }
          heigth += 20;
          width = 0;
        }
    }
    Je parcours mon tableau de case en case en checkant quel entier est contenu dans la case, et en y placant l'item (et donc l'image) correspondant, a la largeur (width) et la hauteur (heigth) donnée. Puis je décale la largeur de 20, les images faisant elles mêmes 20 pixels.
    Si la case contient un 0, elle est donc vide, il n'y a rien a afficher, je decale la largeur de 20 et passe a la case suivante.

    Mais lorsque je modifie la position de mon serpent, c'est a dire en modifiant la position des 2, 3 et 4 dans mon tableau, l'affichage dans ma fenetre lui ne bouge pas. Il reste tel qu'il est sur le screen ci dessus. En clair ma fenêtre n'est pas animée, elle reste a la position initiale du tableau.

    Je pense que les items une fois positionnés dans ma scène, ne peuvent pas être chevauchés par de nouveaux items, et ainsi l'image reste fixe. Mais étant un débutant total en Qt, je ne suis pas du tout sur de ce raisonnement et surtout je n'ai aucune idée de comment résoudre mon problème.

    Merci d'avance pour les réponses que vous pourrez m'apporter

  2. #2
    Rédacteur

    Avatar de johnlamericain
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    3 742
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Royaume-Uni

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

    Informations forums :
    Inscription : Août 2004
    Messages : 3 742
    Par défaut
    C'est une solution pas du tout optimisé tout ça sachant que certains de tes éléments ne bougent pas

    Disons que tu as prévu une étape d'optimisation plus tard, essaye un sur ta scène à chaque rafraichissement.

  3. #3
    Membre éprouvé
    Avatar de GreatTux
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2009
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Indre et Loire (Centre)

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

    Informations forums :
    Inscription : Octobre 2009
    Messages : 77
    Par défaut
    Hello,

    Les items de ta scène peuvent être déplacés, superposés par d'autres etc. Pas de contraintes à ce niveau là.

    Je pense que c'est plutôt un problème de conception.

    Si tu veux pouvoir déplacer les items existants, tu dois garder un pointeur vers ton QGraphicsItem et ne pas en recréer un à chaque fois, est-ce bien ce que tu fais?

  4. #4
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Idem, je pense que tu as un (très gros ?) problème de conception. Tu ne fais pas du tout de la POO là, tu as une fonction qui fait tout le boulot.
    Il faudrait plutôt surcharger des QGraphicsPixmapItem pour faire ton snake (ou un QGraphicsGroupItem pour avoir plusieurs pixmaps), tes mures, ton sol, etc. Et définir un comportement pour chaque classe dérivée (la pomme disparait quand elle est avalée par le serpent, le serpent grandi quand il mange, meurt quand il se fait une bosse, etc.)

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 20
    Par défaut
    Wow tout d'abord merci a vous trois pour la rapidite de reaction!

    J'etais sur que c'etait pas optimise

    J'ai tente un scene->clear(); a chaque debut de boucle mais ca n'a pas fonctionne.

    Pour ce qui est du pointeur, non j'en recreais bien un a chaque fois en effet (d'ailleurs je me rends compte que je ne vous ai pas mis tout le code, c'est maintenant chose faite : )

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    void    QtAff::AffMap(int **tab, int size, QGraphicsScene *scene)
    {
      QPixmap image;
      int   width = 0;
      int   heigth = 0;
     
      for (int i = 0; i < size; i++)
        {
          for (int j = 0; j < size; j++)
            {
              if (tab[i][j] == 1)
                {
                  image.load("./res/mur.png", 0, Qt::AutoColor);
                  _mur = scene->addPixmap(image);
                  _mur->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 4)
                {
                  image.load("./res/tete.png", 0, Qt::AutoColor);
                  _tete = scene->addPixmap(image);
                  _tete->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 2)
                {
                  image.load("./res/queue.png", 0, Qt::AutoColor);
                  _queue = scene->addPixmap(image);
                  _queue->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 3)
                {
                  image.load("./res/corps.png", 0, Qt::AutoColor);
                  _corps = scene->addPixmap(image);
                  _corps->setPos(width, heigth);
                  width += 20;
    }
              if (tab[i][j] == 4)
                {
                  image.load("./res/tete.png", 0, Qt::AutoColor);
                  _tete = scene->addPixmap(image);
                  _tete->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 2)
                {
                  image.load("./res/queue.png", 0, Qt::AutoColor);
                  _queue = scene->addPixmap(image);
                  _queue->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 3)
                {
                  image.load("./res/corps.png", 0, Qt::AutoColor);
                  _corps = scene->addPixmap(image);
                  _corps->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 7)
                {
                  image.load("./res/apple.jpg", 0, Qt::AutoColor);
                  _apple = scene->addPixmap(image);
                  _apple->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 0)
                width += 20;
            }
          heigth += 20;
          width = 0;
        }
    }
     
    int     main(int argc, char *argv[])
    {
      QApplication app(argc, argv);
      QGraphicsScene *scene = new QGraphicsScene;
      QtAff Aff;
      int size = 25;
      int **tab = Aff.creat_tab(size);
      int dir = UP;
      int cpt = 0;
     
      Aff.setWidth(520);
      Aff.setHeigth(520);
      while (1)
        {
          scene->clear();
          Aff.AffMap(tab, size, scene);
          QGraphicsView vue(scene);
          vue.setFixedSize(Aff.getWidth(), Aff.getHeigth());
          vue.setWindowTitle("Snake");
          vue.show();
          return app.exec();
          Aff.decal(tab, size, dir); // sert a decaler le serpent dans mon tableau d'entiers
       }
    }
    J'ai ecoute ton conseil et ai cree dans ma classe 5 pointeurs representant les 5 items dont j'ai besoin (apple, tete, queue, corps et mur). Changement par rapport a avant donc ou j'utilisais un seul et meme item pour chaque image et qui etait une variable temporaire.
    Mais l'affichage reste tout de meme statique

    Devrais-je utiliser un seul et meme pointeur d'item pour toutes les images et le placer dans ma classe?

    Edit : Pour ce qui est de la conception ne t’inquiète pas, ceci n'est qu'une ebauche et n'est pas du tout finalise, le code sera decoupe et surcharge plus tard, pour l'instant mon seul but est de pouvoir afficher en dynamique graphiquement mon tableau d'entiers.
    Si tu préfères la partie 'core' (gestion du jeu) est faite, il ne me reste que la partie graphique Qt a finir.

    Merci en tous cas de m'avoir déjà éclairé sur certains points.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 20
    Par défaut
    (Desole du doublon)

    Pour faire plus clair je veux juste que ma fonction AffMap() puisse parcourir mon tableau a deux dimensions et afficher 'bêtement' l'image qui correspond a la valeur de chaque case. C'est tout.

  7. #7
    Rédacteur
    Avatar de Amnell
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    1 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

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

    Dans votre main(), vous avez :

    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
    {
      ...
      Aff.setWidth(520);
      Aff.setHeigth(520);
      while (1)
        {
          scene->clear();
          Aff.AffMap(tab, size, scene);
          QGraphicsView vue(scene);
          vue.setFixedSize(Aff.getWidth(), Aff.getHeigth());
          vue.setWindowTitle("Snake");
          vue.show();
          return app.exec();
          Aff.decal(tab, size, dir); // sert a decaler le serpent dans mon tableau d'entiers
       }
    }
    Tel que la boucle est conçue, vous faite l'équivalent de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    {
      ...
      Aff.setWidth(520);
      Aff.setHeigth(520);
      scene->clear();
      Aff.AffMap(tab, size, scene);
      QGraphicsView vue(scene);
      vue.setFixedSize(Aff.getWidth(), Aff.getHeigth());
      vue.setWindowTitle("Snake");
      vue.show();
      return app.exec();
    }
    ... ce qui n'est en réalité pas une boucle. Vous faites un nettoyage inutile de la scène, vous placez tous les éléments dans la scène, vous créez la vue et vous l'affichez à l'écran.

    Jolie norme E... GNU.

    Bonne continuation,
    Amnell.
    N'oubliez pas de consulter la FAQ Qt ainsi que les cours et tutoriels C++/Qt !

    Dernier article : Débuter avec les Enlightenment Foundation Libraries (EFL)
    Dernières traductions : Introduction à Qt Quick - Applications modernes avec Qt et QML
    Vous cherchez un livre sur Qt 5, Qt Quick et QML ? Créer des applications avec Qt 5 - Les essentiels

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 20
    Par défaut
    Bonjour,

    Merci pour votre reponse

    Qt etant tout nouveau pour moi (j'ai commence il y a deux jours), je ne saisis pas encore completement l'usage de toutes ses classes et certaines de mes utilisations doivent vous faire bondir j'en ai conscience

    J'ai quelques peu avance dans mon code, et le resultat est different :

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
     
    void    QtAff::AffMap(int **tab, int size, QGraphicsScene *scene)
    {
      QPixmap       image;
      int   width = 0;
      int   heigth = 0;
     
      for (int i = 0; i < size; i++)
        {
          for (int j = 0; j < size; j++)
            {
              if (tab[i][j] == 1)
                {
                  image.load("./res/mur.png", 0, Qt::AutoColor);
                  item_mur = scene->addPixmap(image);
                  item_mur->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 4)
                {
                  image.load("./res/tete.png", 0, Qt::AutoColor);
                  item_tete = scene->addPixmap(image);
                  item_tete->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 2)
                {
                  image.load("./res/queue.png", 0, Qt::AutoColor);
                  item_queue = scene->addPixmap(image);
                  item_queue->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 3)
                {
                  image.load("./res/corps.png", 0, Qt::AutoColor);
                  item_corps = scene->addPixmap(image);
                  item_corps->setPos(width, heigth);
                  width += 20;
                }
              if (tab[i][j] == 7)
                {
                  image.load("./res/apple.jpg", 0, Qt::AutoColor);
                  item_apple = scene->addPixmap(image);
                  item_apple->setPos(width, heigth);
                  width += 20;
                }
    if (tab[i][j] == 0)
                width += 20;
            }
          heigth += 20;
          width = 0;
        }
    }
     
    int     main(int argc, char *argv[])
    {
      QApplication app(argc, argv);
      QGraphicsScene *scene = new QGraphicsScene; //creation de la scene                                                                                                                                                                         
      QtAff Aff;
      int size = 25;
      int **tab = Aff.creat_tab(size);
      int dir = UP;
      int cpt = 0;
      QGraphicsView vue(scene);
     
      Aff.initWindow();
      vue.setFixedSize(Aff.getWidth(), Aff.getHeigth());
      vue.setWindowTitle("Snake");
      while (1)
        {
          Aff.AffMap(tab, size, scene);
          vue.show();
          app.exec();
          sleep(1);
          Aff.decal(tab, size, dir);
          cpt++;
          if (cpt == 3)
            dir = LEFT;
          if (cpt == 7)
            dir = DOWN;
          if (cpt == 10)
            dir = RIGHT;
        }
      return app.exec();
    }
    J'ai donc retire la création de ma vue et son paramétrage de ma boucle, et retire le return app.exec() pour ne laisser qu'un app.exec().

    Le resultat est le suivant : ma premiere fenetre est la meme que lors de mon premier post, par contre lorsque je la ferme, une deuxieme fenetre apparait, ou on voit que mon serpent s'est deplace, mais que les anciennes images de son corps elles sont restees. Illustration :




    Pour au final donner :



    Mes problemes sont donc les suivants :
    Comment supprimer tous les items de ma scene apres chaque affichage, afin d'eviter que les items ne se superposent? (j'ai essaye de faire un scene->removeItem(item) pour mes 5 pointeurs sur item apres chaque affichage, mais ca segfault )
    Pourquoi l'affichage se fait-il en plusieurs fenetres et non pas en une seule qui s'actualise?

    Merci d'avance pour le temps que vous m'accorderez, et bonne journée !

    PS : Amnell je suis perce a jour

Discussions similaires

  1. Jeu du snake en python
    Par pythonovice dans le forum Général Python
    Réponses: 1
    Dernier message: 24/04/2015, 10h46
  2. Jeu du Snake
    Par aimasdu06 dans le forum C++
    Réponses: 4
    Dernier message: 30/10/2014, 15h36
  3. Réponses: 2
    Dernier message: 23/06/2013, 14h10
  4. Jeu du snake en C
    Par deWeb dans le forum C
    Réponses: 4
    Dernier message: 01/01/2011, 03h18
  5. Quelques questions sur le tile mapping
    Par LexxusEVC dans le forum Développement 2D, 3D et Jeux
    Réponses: 11
    Dernier message: 21/10/2009, 08h33

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