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 :

Collision et limitation du mouvement dans la scène [Graphics View]


Sujet :

Qt

  1. #1
    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 Collision et limitation du mouvement dans la scène
    Bonjour tout le monde,

    J'ai une scène avec différents items. J'aimerais gérer les collisions et limiter les mouvements des différents items à l'intérieur de ma scène (les bords de sceneRect).

    Pour le moment, j'ai créé 4 lignes correspondant aux différents bords de ma scène:
    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
     
    GraphicsScene * scene = new QGraphicsScene(this);
      scene->setSceneRect(0,0, 300, 200);
      QLineF lineTop(scene->sceneRect().topLeft(),
                     scene->sceneRect().topRight());
      QLineF lineBottom(scene->sceneRect().bottomLeft(),
                        scene->sceneRect().bottomRight());
      QLineF lineLeft(scene->sceneRect().topLeft(),
                      scene->sceneRect().bottomLeft());
      QLineF lineRight(scene->sceneRect().topRight(),
                       scene->sceneRect().bottomRight());
      QPen pen(Qt::red);
     
      scene->addLine(lineTop, pen);
      scene->addLine(lineBottom, pen);
      scene->addLine(lineLeft, pen);
      scene->addLine(lineRight, pen);
    J'ajoute ensuite un autre item personnalisé dans la scène. J'ai redéfini les méthodes boundingRect et paint et gère la collision dans cette dernière:
    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
    QRectF Item::boundingRect() const
    {
      return QRectF(0,0, m_width, m_height);
    }
     
    void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
      Q_UNUSED(option);
      Q_UNUSED(widget);
      painter->setBrush(Qt::yellow);
     
      if (scene()->collidingItems(this).size() > 0)
      {
        DoCollision();
      }
     
      painter->drawRect(boundingRect());
    }
     
    void Item::DoCollision()
    {
      //Ce code ne marche pas... mais je m'y attendais
      QPointF newPos = mapToParent(-boundingRect().width(), -boundingRect().width());
      if (!scene()->sceneRect().contains(newPos))
      {
        newPos = mapToParent(0,0);
      }
     
      setPos(newPos);
    }
    Ce que je voudrais faire dans un premier temps, c'est de déplacer l'item en mouvement vers la gauche, la droite, le bas ou le haut d'un pixel seulement en fonction de la ligne qui est touchée.
    Secondement, si l'objet touché est de type item (en gros un second item) alors, je voudrais déplacer en même temps l'autre objet.

    J'ai bien une idée pour faire ces deux étapes mais je ne sais pas si c'est optimal:
    - Faire une classe contenant un type énuméré avec une méthode virtuelle pour tester le type.
    - Faire hérité cette classe par tous mes QGraphicsItem
    - Au niveau de paint(), récupérer tous les items qui sont en collision avec l'item courant et appliquer un déplacement en fonction du type d'objet.

    J'ai l'impression de me compliquer la vie mais je ne vois pas comment faire autrement...

    Si vous avez des idées, n'hésitez pas!

    Merci

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


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 897
    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 897
    Points : 219 643
    Points
    219 643
    Billets dans le blog
    125
    Par défaut
    Bonjour,

    Comment gérez vous les mouvements de vos éléments ?
    Vous ne devriez pas faire le déplacement, ni la vérification de collision dans paint, mais dans une fonction "update" qui met à jour, si besoin la position de l'élément en cours.

  3. #3
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 721
    Points : 43 825
    Points
    43 825
    Par défaut
    Regardes l'exemple collinding mice fourni avec Qt

  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
    Merci pour vos réponses.

    @LittleWhite: en fait la méthode "update" appelle la méthode paint donc je ne pense pas que ça change grand chose au niveau performance.
    @chrtophe: Je suis entrain de regarder ça, et ça semble bien correspondre. Pour le moment, j'ai réussi à faire la collision entre les différents éléments de ma scène mais pas de blocage au niveau des bords du rectangle de ma scène.

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


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 897
    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 897
    Points : 219 643
    Points
    219 643
    Billets dans le blog
    125
    Par défaut
    Bah, la fonction update ne devrait pas appeler paint() non plus (enfin, c'est ma façon de voir les choses )

  6. #6
    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
    @LittleWhite: c'est l'implémentation de Qt (qui peut sans doute être améliorée).

    Sinon, j'ai réussi à faire tout ce que je voulais:
    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
    void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
      Q_UNUSED(option);
      Q_UNUSED(widget);
      painter->setBrush(Qt::yellow);
     
      //Pour tous les éléments qui sont en collisions avec l'élément courant.
      for (QGraphicsItem * item : scene()->collidingItems(this))
      {
        DoCollision(item);
      }
     
      painter->drawRect(boundingRect());
    }
     
    void Item::DoCollision(QGraphicsItem * item)
    {
      //on déplace l'élément en collision par le delta du déplacement.
      item->moveBy(m_deltaX, m_deltaY);
      item->update();
    }
     
    // On limite le mouvement à l'horizontal et à l'intérieur de la scène.
    void Item::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
      m_deltaX = event->pos().x() - event->lastPos().x();
      m_deltaY = event->pos().y() - event->lastPos().y();
      //On récupère la nouvelle position en fonction de la position de la souris
      QPointF newPos(mapToParent(event->pos().x(), 0) - mapToParent(event->buttonDownPos(Qt::LeftButton)));
      newPos = mapToParent(newPos.x(), 0);
     
      //On empêche le déplacement en dehors des bordures de rectangle de la scene.
      if (newPos.x() < scene()->sceneRect().x())
      {
        newPos.setX(scene()->sceneRect().x());
      }
      else if (newPos.x() + boundingRect().width() > (scene()->sceneRect().x() + scene()->sceneRect().width()))
      {
        newPos.setX(scene()->sceneRect().x() + scene()->sceneRect().width() - boundingRect().width());
      }
     
      if (newPos.y() < scene()->sceneRect().y())
      {
        newPos.setY(scene()->sceneRect().y());
      }
      else if (newPos.y() > scene()->sceneRect().height())
      {
        newPos.setY(scene()->sceneRect().height());
      }
     
      setPos(newPos);
      update();
    }
    Merci pour tous les conseils!

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

Discussions similaires

  1. Irrlicht 3D : Mouvement d'objets dans une scène
    Par LittleWhite dans le forum Développement 2D, 3D et Jeux
    Réponses: 0
    Dernier message: 22/04/2013, 20h12
  2. [AWT]Limiter le mouvement de la souris
    Par Le prophete dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 31/08/2004, 09h59
  3. probleme mouvement dans un paysage
    Par nonoRedDevils dans le forum OpenGL
    Réponses: 24
    Dernier message: 24/06/2004, 12h12
  4. limiter la saisie dans un edit à des réels!!!
    Par shout dans le forum Windows
    Réponses: 10
    Dernier message: 21/06/2004, 16h20
  5. Comment limiter les mouvements du curseur??
    Par scorpiwolf dans le forum C++Builder
    Réponses: 9
    Dernier message: 07/07/2002, 22h09

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