Ralentissement des performances sur une implémentation A * dans un jeu de tower defense


9

Je fais un jeu Tower Defense en Flash sans chemin prédéfini.

Bien que ma grille soit 40x40 (petite?), A * a du mal à recalculer à chaque fois. J'ai donc fait ma propre modification pour faciliter le recalcul et le nombre de cellules touchées a chuté à environ 900 (lors de la modification près de la racine). Il se fige encore pendant une durée très courte, mais détectable, lorsqu'une nouvelle tour est placée.

Est-ce un problème d'implémentation, ou est-ce que le 40x40 est trop?

Éditer:

La structure de mon code:

  • Toutes les données sont enregistrées dans un tableau 2D de cellules.
  • Chaque cellule contient son parent dans la direction du chemin (1-8 dans le sens des aiguilles d'une montre) et le tableau codé au niveau du bit de ses enfants dans le chemin (chaque bit représente un enfant).
  • La recherche est effectuée par A * avec l'estimation de la distance euclidienne.

Vous allez devoir être beaucoup plus précis ici. Nous n'avons aucune idée de l'apparence de votre code, de sa structure, etc., et nous ne pouvons donc tirer aucune conclusion sur ce qui le ralentit.
Sean James

1
Lorsque j'ai implémenté A * pour la dernière fois, je me souviens qu'il fonctionnait à travers une grille 64x64 en 1 ms maximum . Donc oui, cela semble être un problème avec votre implémentation. Je suggère de publier votre code ou l'essentiel afin que nous puissions vous aider davantage.
Marc Müller

Voir la modification que j'ai ajoutée
Dani

1
Si 40x40 est trop lent, il y a de fortes chances que vous fassiez quelque chose de très mal. Publiez votre code ou profilez-le. Sinon, augmentez-le et voyez ce qui se passe - si une grille 80x80 prend plus de quatre fois plus de temps, vous avez quelque chose d'extrêmement cassé.
ZorbaTHut

Le titre peut-il être un peu plus informatif, s'il vous plaît?
tenpn

Réponses:


4

Je ne peux pas commenter, mais premier profil dans Flex, tout le reste est une conjecture.


Comment puis-je profiler un projet flash en flex?
Dani

Oui et non. Je ne pense pas que vous chargez le projet flash directement. Je pense que vous pourriez peut-être profiler le swf sans source et toujours obtenir des informations sur le niveau de fonction. Je ferais une recherche google pour "profiler un projet flash en flex" ou similaire. J'ai fait et obtenu ceci: flexblog.edchipman.ca/… qui semble prometteur.
Jonathan Fischoff

Merci, m'a vraiment aidé à trouver la partie problématique (n'était pas dans l'algorithme, voir le commentaire sur la question)
Dani

13

Je suppose que la TD est «Tower Defense»

Je pense que A * va un peu trop loin pour cela.

Au début du jeu, remplissez la zone de jeu des points de sortie pour créer une carte de mouvement:

 |---------|
 |5|4|3|3|3|
 |5|4|3|2|2|
->5|4|3|2|1->
 |5|4|3|2|2|
 |5|4|3|3|3|
 |---------|

et le mouvement est toujours vers un carré avec une valeur inférieure.

Lorsque le joueur place une tour, mettez à jour chacun des huit carrés adjacents: pour chaque carré, définissez sa valeur de mouvement à un de plus que la valeur adjacente la plus basse. Si la valeur change, répétez le processus centré sur le carré mis à jour. Ensuite, pour vérifier que l'itinéraire vers la sortie n'est pas bloqué, assurez-vous que tous les carrés sont adjacents à un carré de valeur inférieure.

Lorsque le joueur supprime une tour, définissez la valeur de mouvement sur un de plus que le carré adjacent le plus bas et répétez le processus ci-dessus.

Une approche plus simple serait de refaire le remblayage.


6
Refaire le remplissage par inondation coûte plus cher que de faire A * pour un petit nombre d'unités - à peu près, la longueur de la carte - au moins en termes algorithmiques (et comme il s'agit de Flash, les constantes non algorithmiques comme la disposition de la mémoire peuvent probablement '' t être utilisé très efficacement). Cependant, il s'agit d'un très bon modèle pour de nombreuses unités communicantes, et est appelé diffusion collaborative - scalablegamedesign.cs.colorado.edu/wiki/Collaborative_Diffusion .

@Joe Wreschnig: wow joli lien. J'ai déjà utilisé cette technique mais je n'ai jamais su comment elle s'appelait. Merci.
tenpn

@Joe, tant qu'il y a au moins quelques barrières sur la carte, je ne pense pas que ce serait plus inefficace que d'appeler A *. C'est-à-dire que je ne pense que pour une carte grande ouverte, presque sans obstacle avec peu d'unités, cela pourrait être pire.
edA-qa mort-ora-y

@edA: Par définition, un remblai doit finalement toucher tous les points accessibles sur la carte; A * fournit des limites supérieures éprouvées pour le nombre de points qu'il doit toucher, qui est au plus chaque point accessible sur la carte et généralement beaucoup moins. Le remplissage d'inondation est un algorithme plus simple pour optimiser des choses comme la disposition de la mémoire, mais comme je l'ai dit, dans Flash, cela n'a probablement pas d'importance.

@Joe, c'est ce que je dis, c'est que même avec seulement une poignée de tours, le A * touchera probablement presque tous les espaces. Mais pour N monstres, il suffit de dépasser total_squares / N pour être moins efficace que le remblai.
edA-qa mort-ora-y

2

Étrange, je pensais avoir répondu à cela, mais la réponse semble avoir disparu. Faites votre algorithme de recherche de sorte qu'il puisse être mis à jour en plusieurs étapes, de sorte que lorsque vous placez une tour et jouez une animation, vous pouvez faire un peu chaque image et vous aurez entre une demi-seconde et une seconde pour mettre à jour votre Un * sans pause notable. C'est la latence - si vous ne pouvez pas l'accélérer, trouvez un moyen de le cacher. Jouer une animation tout en plaçant une tour serait naturel pour un jeu et imo un bon endroit pour le cacher.


C'est une bonne idée en général, mais mauvaise pour cette question spécifique. Un * sur une si petite grille devrait être presque instantané, ne prenant pas beaucoup de temps.
davr

C'est suffisant. C'est la seule réponse que je pourrais donner qui résoudrait le problème sans connaître les détails de mise en œuvre qui provoqueraient le ralentissement.
Kaj

0

Pour commencer, vous pouvez changer votre tableau en vecteur - devrait vous donner quelques améliorations de vitesse. Postez le code et nous pourrons peut-être suggérer plus d'optimisations.


0

Je suppose que votre ralentissement est dû au fait que vous calculez un chemin pour tous les personnages simultanément. Le calcul d'un chemin pour un personnage est rapide, mais s'il y a deux douzaines de personnages dans la scène, cela peut s'enliser.

Au lieu de cela, vous devez répartir la charge sur quelques images. Étalez vos mises à jour de l'IA afin que différents personnages mettent à jour leur chemin sur différentes images. Ce serait vraiment perceptible si un personnage ne réagissait qu'une seconde plus tard, mais une seule image ne provoquerait pas de mauvaises réactions.


Cela a été répondu il y a près d'un an et n'a été heurté qu'en raison du travail d'édition de Grace. (Cela n'avait rien à voir avec trop de personnages.)

Merci de me le faire savoir. Je n'ai pas remarqué les dates.
jhocking le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.