Bonjour,
Pour un jeu en 2D que je suis en train de développer, j'ai implémenté l'algorithme A* pour le déplacement des ennemis.
L'algo à l'air de pas trop mal marcher, sauf que le calcul du chemin est très lent : Pour déplacer un personnage de 200 pixels, le calcul dure environ 15 secondes.
Je me suis inspiré de ce tuto : http://khayyam.developpez.com/articles/algo/astar/
Ce qui ralenti mon calcul c'est le test de collision (fonction ajouter_cases_adjacentes du tuto) à la ligne :
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 if (*((Uint8 *)s->pixels + j * s->pitch + i * s->format->BytesPerPixel) == NOIR) /* obstace, terrain non franchissable, on oublie */ continue;
Sauf que j'utilise un quadtree pour optimiser les tests de collisions justement, mais bon ma fonction de test de collision marche bien je l'ai testé.
Le problème vient du fait que mes ennemis se déplacent au pixel près, pas par case (tiles), du coup cette fonction est appelée plusieurs fois par pixel analysés.
Ma classe QuadTreeNode :
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 class QuadTreeNode { public: [...] sf::IntRect getBounds() const; bool isCollision (Collisionnable *c, sf::Vector2i p); // Renvoie true si le point passé en paramètre est en collision avec un autre objet que celui passé en paramètre private: QuadTreeNode *m_ParentNode; sf::IntRect m_Bounds; QuadTreeNode *m_ChildNodes[4]; // Dans l'ordre : NE SE SW NW std::vector<Collisionnable*> m_Objets; };
L'implémentation de ma méthode isCollision du quadtree :
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
23
24
25
26 bool QuadTreeNode::isCollision(Collisionnable *c, sf::Vector2i p) { for (unsigned int i = 0; i < m_Objets.size(); i++) { if (m_Objets[i] != c) { sf::IntRect b = m_Objets[i]->getBounds (); if (b.contains(p)) return true; // si je commente cette ligne le calcul est quasiment instantané } } for (unsigned int i = 0; i < 4; i++) { if (m_ChildNodes[i] != 0) { sf::IntRect b = m_ChildNodes[i]->getBounds (); if (b.contains(p)) { if (m_ChildNodes[i]->isCollision(c, p)) return true; // si je commente cette ligne le calcul est quasiment instantané également } } } return false; }
Et voici comment j'appelle cette fonction dans ajouter_cases_adjacentes() :
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 if (m_Map->getQuadTree()->isCollision(this, sf::Vector2i (i,j))) { // obstacle, terrain non franchissable, on oublie continue; }
Pour déplacer un personnage de la coordonnée 865,466 à la coordonnée 600,449 (il y a des obstacles entre le point de départ et le point d'arrivée) cette fonction est appelée 2096504 fois par la fonction ajouter_cases_adjacentes().
Merci d'avance pour votre aide...
Partager