Dans le jeu 2D avec lequel je travaille, le moteur de jeu est en mesure de me donner, pour chaque unité, la liste des autres unités qui sont dans sa plage de vue.
Je voudrais savoir s'il existe un algorithme établi pour trier les unités en groupes , où chaque groupe serait défini par toutes ces unités qui sont «connectées» les unes aux autres (même par d'autres).
Un exemple pourrait aider à mieux comprendre la question (E = ennemi, O = propre unité). D'abord les données que j'obtiendrais du moteur de jeu:
E1 can see E2, E3, O5
E2 can see E1
E3 can see E1
E4 can see O5
E5 can see O2
E6 can see E7, O9, O1
E7 can see E6
O1 can see E6
O2 can see O5, E5
O5 can see E1, E4, O2
O9 can see E6
Ensuite, je devrais calculer les groupes comme suit:
G1 = E1, E2, E3, E4, E5, O2, O5
G2 = O1, O9, E6, E7
On peut supposer sans risque qu'il existe une propriété commutative pour le champ de vision: [si A voit B, alors B voit A].
Juste pour clarifier: j'ai déjà écrit une implémentation naïve qui boucle sur chaque ligne des informations sur le moteur de jeu, mais à première vue, cela semble un problème assez général pour qu'il ait été étudié en profondeur et dispose de divers algorithmes établis (peut-être en passant à travers une structure arborescente?). Mon problème est que je n'ai pas pu trouver un moyen de décrire mon problème qui a renvoyé des hits google utiles.
Merci d'avance pour votre aide!
Réponses:
Si votre relation "peut voir" est symétrique, de sorte que "A peut voir B" implique "B peut voir A", alors les groupes que vous souhaitez calculer sont les composants connectés du graphique défini par la relation "peut voir". Comme d'autres l'ont noté, il existe des algorithmes simples pour les calculer, tels que:
(Une file d'attente ou toute autre collection qui implémente efficacement les opérations "ajouter un nouvel élément" et "supprimer et renvoyer un élément" peut être utilisée à la place de la pile
s
ci-dessus.)Si votre relation "peut voir" n'est pas symétrique, vous devez décider si vous voulez que vos groupes soient les composants fortement ou faiblement connectés. Pour les composants faiblement connectés, l'algorithme ci-dessus fonctionnera tel quel, sauf que la ligne
for each unit w that v can see
doit être remplacée parfor each unit w that can see v, or that v can see
. Pour les composants fortement connectés , vous pouvez utiliser l'un des algorithmes ( Kosaraju , Tarjan ou Gabow ) mentionnés sur la page Wikipédia liée.Pour les relations non symétriques, vous pouvez également vouloir calculer la fermeture transitive de la relation ou de ses composantes fortement connectées. Pour cela, vous pouvez utiliser l' algorithme Floyd – Warshall ; voir cette réponse sur SO pour (un peu) plus d'informations.
Ps. Comme l'article Wikipedia que j'ai lié aux notes ci-dessus, il peut être plus efficace de mettre à jour dynamiquement les groupes à mesure que la relation de visibilité change. Je ne suis pas familier avec les algorithmes avancés (?) Mentionnés sur Wikipédia, mais il ne devrait pas être difficile de bricoler quelque chose qui bat au moins le recalcul des groupes à partir de zéro à chaque fois.
La moitié de cela est facile: si deux unités de groupes différents acquièrent une ligne de vue entre elles, fusionnez les groupes. Gérer les unités qui se perdent de vue est un peu plus délicat; une solution simple mais peut-être pas optimale consiste à réexécuter l'algorithme de regroupement pour les unités du groupe affecté chaque fois que cela se produit. Vous pouvez y apporter quelques optimisations, si les changements de visibilité se produisent une paire d'unités à la fois:
la source
Ce que vous avez est un graphique de connectivité. Et généralement, la meilleure façon de regrouper les nœuds connectés (c'est-à-dire les caractères) est d'utiliser un algorithme de recherche de graphes. Profondeur d'abord, largeur d'abord, selon le cas. Tout ce que vous faites est de créer une liste des nœuds accessibles depuis tous les autres. Tant que votre graphique n'est pas orienté (si A est visible pour B, alors B est visible pour A), cela fonctionne très bien.
Il peut y avoir des algorithmes pour améliorer cela pour des cas spécifiques. Par exemple, si parfois les personnages ne bougent pas (et le terrain ne bouge pas aussi, de sorte que les personnages immobiles restent visibles), vous pouvez choisir de ne pas les tester à nouveau pour mettre à jour leurs graphiques de connectivité.
Mais en général, vous devrez retester la visibilité à chaque image. Les chances sont que cela va être plus lent que le parcours du graphique pour trouver les groupes de visibilité.
la source
Cela ressemble à un problème de connectivité graphique standard. Il peut y avoir une sorte d'algorithme pour cela, et il pourrait ressembler à ceci:
Je m'attends à ce qu'il soit possible de l'implémenter via un arbre, comme le clustering hiérarchique, mais je doute que cela fonctionnerait plus rapidement - les arbres ont tendance à être O (log N) alors que la plupart des vérifications que je donne ci-dessus peuvent être implémentées comme O (1) .
la source
Je suis d'accord avec tous ceux qui ont répondu qu'il s'agissait d'un problème de connectivité graphique, mais permettez-moi de souligner que ce dont vous avez besoin ici est le graphique de triangulation Delaunay généré à partir de toutes vos unités pertinentes. Cela garantit que seules les unités les plus proches les unes des autres seront connectées dans le graphique que vous générez. Il vous sera très difficile de procéder de cette manière, car les croisements de graphiques (non-planarité) entraîneront des unités trop éloignées les unes des autres pour être incorrectement connectées dans le graphique.
Ce qui précède ne s'applique que si vous utilisez un espace continu (comme dans la plupart des FPS à mouvement libre); cependant, si vous avez déjà une grille sous-jacente (un graphique planaire) sur laquelle vos unités se déplacent, vous pouvez simplement l'utiliser pour évaluer la connectivité à la place.
la source