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 :

Gestion des événements [2D/3D]


Sujet :

Qt

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Points : 7
    Points
    7
    Par défaut Gestion des événements
    Bonjour,

    Depuis quelques semaines maintenant j'essaye de programmer un petit jeu 2D en utilisant Qt, jusqu'à présent je n'ai rencontré aucun réel problèmes, mais là je dois dire que je bloque complètement.

    Je vous explique mon problème, je crée une map à partir d'un fichier xml en dessinant chaque cases (Tiles) sur un QImage que je stocke ensuite dans l'instance de la classe Map ainsi créée.

    Cependant si pour une raison ou une autre, je veux mettre à jour une de ces Tiles, j'ai mis en place un système de signal relié à un slot qui met à jour le QImage de l'instance. Le problème c'est que ce système ne fonctionne pas, mon premier réflexe a été de vérifier mon code, dans lequel je n'ai trouvé aucun soucis, ensuite j'ai tenté de débugger le code et là comme par magie, le code fonctionne, la Map se met à jour. N'y comprenant plus rien je m'adresse à vous.

    Pour vous aidez à mieux cerner mon problème voici le code "fautif":

    map.cpp
    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
    #include "map.h"
     
    Map::Map(QString filename)
    {
        _tilesets = new QHash<QString, Tileset>();
        _layers    = new QVector<QVector<Tile*>* >();
     
        QFile *file = Map::loadFile(filename);
     
        _reader = new QXmlStreamReader(file->readAll());
        parse();
        QPixmap p = createPixmap();
        setImage(p);
        setRect(p.rect());
     
        QVectorIterator<QVector<Tile*>* > layers(*_layers);
        while(layers.hasNext())
        {
            QVector<Tile*> layer = *layers.next();
            for(int i=0; i<layer.size(); i++)
            {
                Tile* t = layer.value(i);
                Map::connect(t, SIGNAL(changed()), this, SLOT(reloadPixmap()));
            }
        }
    }
     
    void Map::reloadPixmap()
    {
        setImage(createPixmap());
    }
     
    Tile* Map::getTile(int layer, int idx) const
    {
        Tile *t = _layers->at(layer)->value(idx);
        return t;
    }
    tile.cpp
    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
    #include "tile.h"
     
    Tile::Tile(QPixmap image, QPoint pos, bool walkable):
        Drawable(image, pos), _walk(walkable)
    {
    }
     
    bool Tile::isWalkable() const
    {
        return _walk;
    }
     
    void Tile::changeImage(QPixmap newImage)
    {
        _image = newImage;
        emit changed();
    }
    mainwindow.cpp
    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 MainWindow::keyPressEvent(QKeyEvent *KeyEvent)
    {
        switch(KeyEvent->key())
        {
            case Qt::Key_Escape:
                close();
                break;
            case Qt::Key_A:
                Tileset t = ((Map*)_map)->getTileset("main");
                Tile *tt = ((Map*)_map)->getTile(0, 1);
                tt->changeImage(t.getPixmap(14));
                break;
        }
    }

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Sans débogueur, utilisez des QDebug() pour voir vous reproduisez le bogue et le tracer.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Points : 7
    Points
    7
    Par défaut
    Merci pour votre réponse, cependant j'ai justement utilisé un débogueur, celui de qtcreator, et le problème c'est que quand je fais tourner le code dans le débogueur il fonctionne.

    Je vais quand même essayer de mettre des traces avec qdebug et voir si je ne peux pas trouver le problème comme ça quand même.

  4. #4
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Bonjour,

    Il est possible que le problème vienne au niveau de la copie de l'image:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Tile::changeImage(QPixmap newImage)
    {
        _image = newImage; 
        emit changed();
    }
    Vous devriez essayer de passez newImage en référence constante et de faire une copie avec la fonction copie de la classe QPixmap:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Tile::changeImage(const QPixmap & newImage)
    {
        _image = newImage.copy();
        emit changed();
    }

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Points : 7
    Points
    7
    Par défaut
    Merci pour votre réponse, j'ai essayé cette solution, mais toujours aucun changement. Je suis entrain de me dire que le plus simple serai de créer dynamiquement la map à chaque frame, je voulais cependant éviter autant que possible cette solution qui diminue les performances; surtout sur des maps qui restent statiques.

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Pour commencer, j'aurais envie de dire qu'un QVector de QVector, c'est relativement moyen comme tentative de créer un tableau 2D...

    Surtout que tu crées un QVector de pointeurs sur QVector... Il y a, très clairement, une indirection en trop

    Si ta carte ne s'étend pas trop dans les deux directions, pourquoi ne créerais tu pas un tableau à une dimension qui contiendrait (nombre de lignes * nombre de colonnes) éléments?

    Tu pourrais accéder à tes différentes tuiles au travers de la formule index = (index de ligne recherchée * nombre de colonnes) + index de colonne recherchée.

    Dans bien des cas, cela te facilitera énormément la tâche et une chose est sure : Si cela n'améliore pas les performances (parce que la carte est trop étendue), cela ne nuira en tout cas absolument pas. Par contre, sur des cartes de petite taille ou de taille moyenne, cela peut les booster pas mal : je te passe les détails, mais disons que ca permet une meilleure utilisation du cache du processeur

    Pour quand même essayer de répondre à ta question, je ne suis pas sur que le slot auquel tu dois connecter ton signal changed() soit réellement le sot reloadPixmap... A moins que le nom du signal n'ait vraiment été mal choisi

    Ce que tu dois faire lorsque tu change une tuile, c'est provoquer la mise à jour de l'affichage et donc de ta scene et / ou de ta vue.

    En effet, si je me base sur le nom du signal uniquement, tu demandes au système de recharger les différentes images. Mais les images, elles ont été chargées, autrement, elles ne serait pas dans ta matrice

    Ce n'est donc pas cela qu'il faut faire, mais bien signaler à ta vue ou à ta scene "qu'il y a quelque chose de changé" pour qu'elle puisse mettre l'affichage à jour en conséquence

    Enfin, il y a quand même quelque chose qui me chagrine dans le code
    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 MainWindow::keyPressEvent(QKeyEvent *KeyEvent)
    {
        switch(KeyEvent->key())
        {
            case Qt::Key_Escape:
                close();
                break;
            case Qt::Key_A:
                Tileset t = ((Map*)_map)->getTileset("main");
                Tile *tt = ((Map*)_map)->getTile(0, 1);
                tt->changeImage(t.getPixmap(14));
                break;
        }
    }
    C'est le transtypage (c_style qui plus est!!!) du membre _map en Map * !!!

    Ce type de transtypage est hyper dangereux car il signifie, en gros "tu peux me croire sur parole, le membre _map (qui est connu comme étant autre chose qu'un pointeur sur Map) est bel et bien un pointeur sur map" que le compilateur, en brave petit soldat, ne se posera absolument aucune question quant à savoir si c'est vrai ou non.

    En plus, ce transtypage est -- a priori -- totalement inutile : Tu as créé un type particulier (Map), pourquoi ne pas faire en sorte que ta classe MainWindow connaisse le membre _map en tant qu'un objet de type Map

    Après, on peut discuter de l'intérêt d'en faire un pointeur ou non, mais, a priori, il n'y a de toutes manières aucune raison pour que ta fenêtre principale connaisse ta carte sous la forme d'un autre type que le type Map
    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

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Points : 7
    Points
    7
    Par défaut
    Tout d'abord, je te remercie (koala01) grandement, à la fois de ta patience pour tenter de décoder mon code (et surtout pour supporter la vue de celui-ci). Tes remarques m'ont aidé à améliorer mon code.

    Ceci dit, j'annonce que le problème est en partie résolu, et provenais de la méthode d'accession à la Tile qui était déclarée comme constante. Cependant, il reste un problème, la fenêtre ne met l'image de la carte à jour que lorsque je clique en dehors de celle-ci. Je ne vois pas d'où cela peut venir, mais je n'ai pas encore une grande expérience de Qt. (ni de c++ d'ailleurs).

    J'aimerais clarifier certains points qui, au vu des réponses et des remarques qui m'ont été faites ne sont pas tout à fait clair pour vous.

    • La structure de la map:
      Qt gérant la transparence alpha, il est possible de superposer deux tuiles.
      Pour gérer cela j'utilise un système de couches que je dessine à l'écran les une après les autres. Ce qui donne comme modèle un QVector contenant les couches, chacune de celle-ci étant représentées par un autre QVector contenant les Tiles (tuiles) ou cases de la map.
    • L'interaction SIGNAL-SLOT:
      Mes tuiles possèdent un SIGNAL appelé changed(), ce SIGNAL est émit dès que l'image de la tuile change.
      Le SLOT reloadPixmap() de la map permet de recharger l'image interne de la map, qui se trouve être statique et générée dans le constructeur.

      Ce que je fais dans mon code c'est juste connecter chacune des Tiles au SLOT reloadPixmap() de la map via le SIGNAL changed(); ce qui, en théorie devrait permettre de mettre à jour la vue, étant donné que pour le moment à chaque frame je redessine l'image de la map.
    • Par rapport au transtypage :
      Celui-ci n'était effectué que pour un test, à la base la map ne devait pas être un pointeur. Je vais d'ailleurs régler ce problème tout de suite.
      Cependant, si quelqu'un voit un réel avantage à l'utilisation d'un pointeur à cet endroit et/ou voudrait plus d'informations concernant ce point particulier, je suis preneur.


    Voila, pour finir mon message, je m'excuse d'avoir attendu aussi longtemps pour répondre, j'ai eu pas mal de boulot ces temps-ci.

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

Discussions similaires

  1. [XML] [EXPAT] xml_parse et la gestion des événements...
    Par Herode dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 05/02/2006, 20h59
  2. Gestion des évènements Netscape 7.0
    Par RATHQUEBER dans le forum Autres langages pour le Web
    Réponses: 6
    Dernier message: 19/12/2005, 16h26
  3. Problème avec la gestion des événements
    Par CynO dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 17/10/2005, 10h07
  4. [JTable] gestion des événements
    Par soulhouf dans le forum Composants
    Réponses: 4
    Dernier message: 19/08/2005, 13h21
  5. Gestion des évènements lors d'un clique sur une image.
    Par yoghisan dans le forum Débuter
    Réponses: 7
    Dernier message: 23/06/2005, 19h04

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