Partage
  • Partager sur Facebook
  • Partager sur Twitter

[SDL] Gérer les collisions avec plusieurs objets

Avec les boîtes de collisions

    30 mars 2008 à 22:03:32

    Salut,

    je fais un petit jeu de plateforme en SDL, et j'en arrive aux collisions.
    J'ai fait pas mal de recherche, et je me suis décidé à utiliser des boîtes de collisions pour gérer les collisions, mais dans tous les tutos et exemples que j'ai trouvé, on ne parle que d'une collision entre deux objets bien défini : c'est toujours "si cet objet entre entre en collision avec celui ci", et je voudrais plutôt "si cet objet entre en collision....tout court", puis faire des tests pour voir d'où vient la collision

    Pourquoi ? Parce que dans un jeu de plateforme, il n'y aura pas juste une plateforme, mais plusieurs.
    J'ai pensé à créer un tableau à deux dimensions qui serait comme ça :

    1. niveau[nombreDObjetDuNiveau][nombreDeBoiteDeCollisionDeLObjet]


    la fonction qui gère les collisions de mon personnage parcourrait ce tableau, mais parcourir tout le niveau à chaque instant, ça m'a l'air un peu neuneu comme solution (je vais néanmoins faire comme ça pour commencer et je modifierai une autre fois si quelqu'un me donne une solution plus judicieuse)

    Merci d'avance
    • Partager sur Facebook
    • Partager sur Twitter
      1 avril 2008 à 20:29:36

      up

      Je me suis mal exprimé, mon problème, plus clairement, c'est que je ne vois pas comment faire pour ne pas avoir à faire des tests de collision avec le personnage et tous les éléments du décor à chaque instant. C'est quand même pas possible qu'on soit obligé de vérifier s'il y collision avec un ennemi qui n'est même pas dans la fenêtre actuelle ?
      • Partager sur Facebook
      • Partager sur Twitter
        4 avril 2008 à 12:38:02

        Ben dernier up avant de me jeter dans un lac mon PC accrocher au cou..
        • Partager sur Facebook
        • Partager sur Twitter
          4 avril 2008 à 13:26:55

          Il y a plusieurs solutions.

          1) A chaque temps, chaque objet vérifie qu'il est pas en collision avec chaque autre objet. C'est facile à implémenter mais peu efficace si le nombre d'objets devient grand (>100).

          2) La position de chaque objet est stockée dans une std::map avec comme clé la position de l'objet. A chaque déplacement, on vérifie que la clé de la map n'existe pas avant d'effectuer le déplacement. Le cas échéant, on gère la collision. Plus difficile à coder, mais plus efficace.

          Il existe encore d'autres méthode si jamais ça ne te suffit pas.
          • Partager sur Facebook
          • Partager sur Twitter
          Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
            4 avril 2008 à 13:41:15

            Salut,
            Effectivement, il y'a une solution qui correspond à ce que tu cheche ;)
            Il te suffit de faire une class BoundingBox, à chaque objet bounding box, tu attache uns surface SDS, et dès que tu détecte une collision entre deux bounding box, tu traite la collision sans te soucier de l'objet :) mais, tu dois classifer tes élément en plusieurs catégories (généralement 2 ou 3 : ennemies, wall, items), puis selon le cas, tu fais ce que t'as à faire ;)
            Voila, en espérant t'avoir été utile.
            • Partager sur Facebook
            • Partager sur Twitter

            La maîtrise des fondamentaux est le fondamental de la Maîtrise.

              4 avril 2008 à 15:13:48

              Merci beaucoup, je mets pas encore le sujet en résolu au cas où j'aurai d'autres questions
              • Partager sur Facebook
              • Partager sur Twitter
                4 avril 2008 à 15:54:26

                De rien ^^
                • Partager sur Facebook
                • Partager sur Twitter

                La maîtrise des fondamentaux est le fondamental de la Maîtrise.

                  5 avril 2008 à 18:14:00

                  Citation

                  Il te suffit de faire une class BoundingBox, à chaque objet bounding box, tu attache uns surface SDS, et dès que tu détecte une collision entre deux bounding box, tu traite la collision sans te soucier de l'objet :)



                  C'est là le problème, tout trier dans des classes, je pense pouvoir le faire (y'a intérêt..), mais c'est le "dès que tu détectes une collision" qui pose problème, comment, sans faire ce que m'a proposé Nanoc en 1, détecter une collision ?

                  Citation

                  1) A chaque temps, chaque objet vérifie qu'il est pas en collision avec chaque autre objet. C'est facile à implémenter mais peu efficace si le nombre d'objets devient grand (>100).



                  Et au passage, c'est quoi une surface SDS , google a pas l'air de connaître :-°

                  Nanoc, en 2 tu me proposes une solution qui correspond surement exactement à ce que je veux, mais après quelques recherches je crois que std::map c'est un "template", et que pour m'en servir il faut que je lise des tutos en anglais ( :waw: , mais j'le ferai), qui parlent d'itérateurs et de je ne sais quoi. Tu dis qu'il existe d'autres méthodes, s'il y en a une que je peux exploiter plus facilement je veux bien.

                  Je retourne aux tutos en anglais :-°
                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 avril 2008 à 18:23:29

                    Salut tout le monde ;)

                    Je suis tombé sur la discussion vraiment par hasard, alors que je cherchais comment gérer le mieux possible une collision sur une trajectoire de sprite.

                    Je suis vraiment intéressé par la seconde solution de Nanoc :

                    Citation : Nanoc

                    2) La position de chaque objet est stockée dans une std::map avec comme clé la position de l'objet. A chaque déplacement, on vérifie que la clé de la map n'existe pas avant d'effectuer le déplacement. Le cas échéant, on gère la collision. Plus difficile à coder, mais plus efficace.


                    Stocker la position du sprite dans la std::map me paraît une très bonne idée, mais si les sprites ne sont pas ponctuels... chacun de ses pixels occupe une position bien précise, non ?
                    Dans ce cas, la vérification ne s'effectuerait que pour un seul des pixels du sprite (celui de la position) ?
                    On ne va quand même pas associer une clé à chacun des pixels "collisionnables" ? Cela me semble très coûteux...

                    Dans le cas de boîtes de collision, on pourrait peut-être stocker seulement 2 pixels : inférieur gauche et supérieur droit, et puis comparer, mais comment ??

                    Je suis vraiment perdu et je comprends le mal de Tjukoz :o
                    • Partager sur Facebook
                    • Partager sur Twitter
                      6 avril 2008 à 19:21:36

                      Il faut effectivement découper l'espace en "boîtes" et stocker chaque élément dans une et une seule boîte à la fois.

                      Pour ce qui est de la map, c'est comme std::vector<>, pas besoin de savoir écrire un template pour l'utiliser.
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
                        7 avril 2008 à 0:47:22

                        Une surface SDL et pas SDS ( faute de frappe :p )
                        Pour ce qui est des optimisations, y'en a une que j'ai développé moi même, tu peux tester les collisions uniquement pour les objets mobiles, c'est vrai, un objet qui bouge peut heurter qelque chose, par contre un objet qui est en arrêt ou fixe n'a nul besoin de tester s'il va entrer en collision, un exemple:

                        1. class personnage
                        2. {
                        3. public:
                        4. personnage();
                        5. ~personnage();
                        6. bool isInCollision(personnage* unAutPerso);
                        7. bool isMoving();
                        8. //et plein d'autres fonctions.
                        9. //Attributs:
                        10. double _speed; //vitesse de déplacement.
                        11. double _direction; //Angle d'orientation du sprite.
                        12. //et plein d'autres variables.
                        13. };
                        14. bool personnage::isMoving()
                        15. {
                        16.     if(_speed != 0)
                        17.         return true;
                        18.     else
                        19.         retrun false;
                        20. }
                        21. bool personnage::isInCollision(personnage* unAutPerso)
                        22. {
                        23.     if(isMoving())
                        24.     {
                        25.         if((unAutPerso->X == (cos(_direction) * _speed) + X) && (unAutPerso->Y == (sin(_direction) * _speed) + Y) ) //Un peu de trigo, ça ne tue personne ^^
                        26.         return true;
                        27.     else
                        28.         return false;
                        29.     }
                        30.     return false;
                        31. }
                        32. };


                        Et voiala :) , optimisé, et tu n'as plus à te soucier des direction (marche pour 360° :p ), si elle n'est pas belle la vie ^^
                        Voila.

                        EDIT:
                        Tu peux généraliser la class, au lieu de faire cela uniquement pour les persos, tu peux faire une class Object, qui représentra toutes les entités de ton jeu (items, personnages, munitions ...) comme ça, t'aura un classe qui gère tout ;)
                        Bonne chance.
                        • Partager sur Facebook
                        • Partager sur Twitter

                        La maîtrise des fondamentaux est le fondamental de la Maîtrise.

                          7 avril 2008 à 3:15:35

                          Ouai j'aime bien ce que fait fissal_houate , moi je vais plus loin en supprimant sa methode isMoving() et en la remplaçant par isMovingLeft(), isMovingRight(), isMovingUp() et isMovingDown().

                          Ba ouai parce que ça sert a rien de tester une collision a droite si ton personnage tombe a gauche...

                          Alors apres c'est sur que tu va éliminer enormément de cas si tu testes uniquement avec les objets a droite de ton perso et dans l'angle de camera ( l'ecran de jeu ).
                          Il y a meme quelque articles qui vont plus loin en découpant ton ecran en plusieurs zones , tu vois genre 9 zones et on teste uniquement avec les objets a droite, qui se trouvent la meme zone ( donc implicitement dans l'angle de caméra ) mais bon c'est inutile la selon moi parce que j'ai rarement vu 200 objets affichés dans la partie droite de l'ecran dans un jeu de plateforme :p

                          Juste une question parce qu'on parle de map , de vector , t'as découpé ton espace en tuiles nan ?
                          • Partager sur Facebook
                          • Partager sur Twitter
                            7 avril 2008 à 8:30:02

                            Encore une fois merci beaucoup, je voudrai juste savoir s'il faut inclure quelque chose pour se servir de la trigo ?
                            • Partager sur Facebook
                            • Partager sur Twitter
                              7 avril 2008 à 10:29:48

                              Un cerveau :) (c'est pas méchant, hein), de la géométrie, et math.h
                              • Partager sur Facebook
                              • Partager sur Twitter

                              [SDL] Gérer les collisions avec plusieurs objets

                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                              • Editeur
                              • Markdown