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

Algorithmes et structures de données Discussion :

2D non isométrique - gestion de profondeur


Sujet :

Algorithmes et structures de données

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut 2D non isométrique - gestion de profondeur
    Bonjour,

    J'ai un petit problème concernant les priorité d'affichage de sprites, dans un environnement 2D. Je commence par vous montrer une petite image, histoire qu'on parle tous de la même chose :

    https://www.dropbox.com/s/5i1fkmj2wt...2015.37.36.png

    Il y a les petits losanges, qui sont des éléments mobiles. Mon programme gère les évènements et je peux faire bouger ces losanges si je le désire.

    Il y a aussi ce mur : c'est un élément qui ne peut pas bouger. Les losanges, s'ils sont derrière ce mur, doivent être affichés derrière le mur, c'est à dire que dans la boucle du programme, on affichera d'abord les losanges qui sont derrière le mur, et ensuite, on affiche le mur par dessus.

    Voilà en gros le cadre.

    S'il n'y avait pas ce mur, la gestion de la profondeur des losanges est très simple : je fais une std::list de pointeur sur sf::Sprite et à chaque boucle du programme, je trie cette liste avec une fonction de comparaison qui compare la position du point le plus bas de chaque losange. Un bout de code sera peut être un peu plus clair (en C++) :

    Code c++ : 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
    bool compare (sf::Sprite* & i, sf::Sprite* & j)
    {
         // on a préalablement mis l'origine des sprites sur le point le plus bas du losange, de sorte que
         // getPosition() retourne les coordonnées de ce point
         return i->getPosition().y < j->getPosition().y;
    }
     
    int main()
    {
         std::list<sf::Sprite*> liste; // une liste de pointeur sur sprites
         // on crée un vector de sf::Sprite et on fait pointer les éléments de liste sur les éléments
         // de ce vector
     
         // boucle du jeu
              // patati patata, on bouge les losanges
              liste.sort(compare);
    }

    Voilà. Avec ça, les losanges sont affichés par ordre de position dans la fenetre.

    Les problèmes arrivent quand j'ajoute le mur : sa base n'est pas horizontale, je définis donc un segment qui correspond à sa base (en diagonale donc). Ce segment est représenté par une paire de points. Puis je procède de la manière suivante : si le losange est au dessus de ce segment, on affiche d'abord le losange, et ensuite, le mur. Si le losange est en dessous, on affiche d'abord le mur, et ensuite le losange. Le principe est en gros le même que pour les losanges entre eux.

    Mais la fonction de tri nécessite donc un traitement différent selon qu'elle compare deux losanges, ou un losange et un mur.

    Je remanie donc ma liste : std::list<std::pair<sf::Sprite*,std::pair<sf::Vector2i,sf::Vector2i>*>> liste;

    Pour les losanges, je n'ai pas besoin de définir un segment, leur position suffit au tri, je laisse donc le pointeur de la paire de points (std::pair<sf::Vector2i,sf::Vector2i>*) à NULL, c'est à dire qu'il ne pointe sur rien du tout. Pour le mur en revanche, ce pointeur pointera sur une paire de points et dans ma fonction de tri, je peux vérifier si la paire pointe sur quelque chose, ou non, autrement dit : si l'objet est statique ou dynamique.

    Et la fonction de tri devient (en C++, encore) :

    Code c++ : 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
    bool compare (std::pair<sf::Sprite*,std::pair<sf::Vector2i,sf::Vector2i>*> & i,
                   std::pair<sf::Sprite*,std::pair<sf::Vector2i,sf::Vector2i>*> & j)
    {
        // cette fonction renvoie vrai si i doit être derrière j, false sinon
     
        // si i statique et j dynamique
        if (i.second != NULL)
            return clockWise(i.second->first + sf::Vector2i(i.first->getPosition()),
                             i.second->second + sf::Vector2i(i.first->getPosition()),
                             sf::Vector2i(j.first->getPosition()));  
     
     
        // si j statique et i dynamique
        if (j.second != NULL)
            return !clockWise(sf::Vector2i(j.first->getPosition()) + j.second->first,
                              sf::Vector2i(j.first->getPosition()) + j.second->second,
                              sf::Vector2i(i.first->getPosition()));
     
        // si i et j dynamiques
        else
            return i.first->getPosition().y < j.first->getPosition().y;
    }

    Voilà où j'en suis. Ce code marche lorsqu'il n'y a dans la fenetre que un objet statique (le mur) et 1 ou 2 objets dynamiques (les losanges). Lorsque je mets plusieurs losanges, la profondeur entre eux est bien gérée, en revanche elle ne l'est pas avec le mur (le screenshot que j'ai mis en lien est juste un cas où ça marche, exceptionnellement).Et je n'arrive toujours pas à trouver mon erreur..

    Je n'ai peut être pas été très clair dans mon explication, je peux bien sûr revenir sur certains points si cela est nécessaire.

    À bientôt, merci par avance
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  2. #2
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Je m'excuse par avance du double post, je sais que ça ne se fait pas Devant le peu de réponses (appréciez comme votre interlocuteur manie avec élégance l'art de la litote) je me dis que l'énoncé de mon problème n'était pas clair du tout. Permettez moi donc de simplifier encore plus le problème, avec une nouvelle image :

    https://www.dropbox.com/s/7twaysuli6...ns%20titre.png

    Mon problème s'apparente à un problème d'ordre de rendu en fonction de la profondeur (en fait, C'EST précisément ce problème).
    Regardons l'image, imaginons que c'est une vue de haut. La ligne rose représente un mur, et les points sont des personnages. Du coup, si la caméra se situait sur la bordure de la fenêtre (en bas), on aurait l'ordre de rendu suivant : point bleu, mur rose, point rouge, point jaune.

    En simplifiant, c'est comme si on triait les points et les lignes entre eux. Trier les points est assez simple, il suffit de les trier par position sur les ordonnées, il n'y a pas de problème là dessus (comme sur un rendu isométrique, en fait). Mais l'introduction du mur pose des problème d'incohérence dans le tri. Par exemple dans cette image :

    https://www.dropbox.com/s/4n75gh0tu3...0-%20copie.png

    -le point bleu est derrière le mur
    -le mur est derrière le point rouge
    -MAIS si l'on regarde les coordonnées en z, le point bleu est devant le point rouge, ce qui explique qu'un algorithme de tri "simple" (insertion, tas, fusion) ne fonctionne pas.

    Comment me dépatouiller avec ça ?
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  3. #3
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Bonjour

    Cherche algorithmes "Z-buffer" et "clipping"

    Tu auras tout ce que tu veux sur ce sujet...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  4. #4
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Hello,

    Merci de ta réponse. La bibliothèque graphique que j'utilise n'est pas assez bas niveau pour gérer un Z Buffer, et je n'en suis pas encore au clipping, pour l'instant, j'aimerais juste trouver un algorithme fonctionnel, on verra la rapidité pour plus tard

    J'ai trouvé une solution, pas franchement terrible : à chaque ligne (obstacle fixe) j'associe un indice. L'obstacle le plus haut (le plus loin) a par exemple l'indice 1, celui d'après, l'indice 3, etc. De 2 en 2 donc. Chaque fois que mes éléments dynamiques bougent, je regarde entre quel et quel obstacle fixe ils sont, et je détermine leur indice. Par exemple si un élément dynamique (les points) est entre l'obstacle 3 et l'obstacle 5, il aura l'indice 4. Ceci constitue la première étape du tri. La deuxième partie du tri consiste à trier les points qui ont le même indice : on les trie par profondeur (hauteur) cette fois.

    Mais ce n'est vraiment pas terrible, et je pense qu'il y a plein de cas particuliers que mon algorithme ne prend pas en compte. Je suis donc preneur de toutes nouvelles idées
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  5. #5
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Pour ceux qui auraient le même problème, je viens de trouver la solution :

    https://www.cs.drexel.edu/~david/Cla...443-newell.pdf

    Cordialement,
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

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

Discussions similaires

  1. avis pour creation d un moteur 2D avec gestion de profondeur
    Par venomelektro dans le forum OpenGL
    Réponses: 12
    Dernier message: 21/07/2010, 19h02
  2. gestion de profondeur pour moteur isométrique
    Par jeremy.joron dans le forum ActionScript 3
    Réponses: 1
    Dernier message: 25/07/2009, 03h11
  3. [E-07] inverse matrice - matrice non inversible - gestion d'erreur
    Par Lnmex dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 11/12/2008, 23h51
  4. Gestion de la profondeur
    Par Jack_serious dans le forum OpenGL
    Réponses: 1
    Dernier message: 06/04/2006, 06h52

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