Page 1 sur 2

pathfinding

Publié : ven. 30/déc./2011 22:46
par blendman
salut

En faisant des recherches j'ai trouvé quelques exemples de pathfinding sur ce forum (Comtois, Huitbit..) :
http://forums.purebasic.com/french/view ... athfinding
http://forums.purebasic.com/french/view ... athfinding
http://forums.purebasic.com/french/view ... athfinding

Mais je cherche une méthode permettant non pas de trouver le chemin le plus court, mais simplement de contourner un obstacle et donc de trouver un chemin. Ce serait pour mes ennemis par exemple.

Sinon, j'ai cherché un tutoriel sur le fonctionnement et l'explication simple du pathfinding A*, mais celui du site du zéro n'existe plus.
Connaissez-vous des tutoriaux intéressants sur A* ?
J'ai trouvé celui-ci, il me semble pas mal du tout :
http://blog.lalex.com/post/2003/09/15/T ... hfinding-A

Merci :)

Re: pathfinding

Publié : sam. 31/déc./2011 13:33
par dayvid
Bonjour blendman :)

Je ne peut pas t'aider car je n'y connais rien la dedans mais c'est un sujet intéressant 8)
Mais c'est compliquer aussi et ma petite tête a du mal a suivre :lol:

Je te souhaite une bonne continuation :D

Re: pathfinding

Publié : sam. 31/déc./2011 17:49
par Mesa
Sur le siteduzero, on trouve un autre tuto :

http://www.siteduzero.com/tutoriel-3-35 ... kstra.html

ici
http://fr.wikipedia.org/wiki/Algorithme_A*
à la fin de l'article, des liens interessants.

et ça
http://awesom.eu/~cygal/archives/2010/0 ... index.html, c'est pas mal.

En attendant...

Mesa.

Re: pathfinding

Publié : sam. 31/déc./2011 17:53
par Fig
On veut bien t'aider, mais on a besoin d'avoir quelques informations... Comment ton monde est modélisé ? Est ce que tu dois éviter beaucoup d'obstacles dynamiques ?

Cas du A*
Si tu as peux d'obstacles dynamique, tu peux relancer le pathfinding plusieurs fois.
Sinon c'est beaucoup plus compliqué. (double pathfinding, un à l'envers, l'autre à l'endroit, en tenant compte du temps...)

Cas du champs de force
Si c'est une sorte de pacman, tu n'as pas besoin de pathfinding, tu "aimantes" tes ennemis à leur cible simplement.

Dans tout les cas, le A* basique est très simple, la seule partie un peu ardue, c'est le trie, selon la méthode que tu emploies.

Re: pathfinding

Publié : sam. 31/déc./2011 23:43
par graph100
celui que je t'avais fournis ne fonctionne pas ? il peut contourner les obstacles non ?

Re: pathfinding

Publié : dim. 01/janv./2012 18:50
par blendman
Mesa : merci pour tes liens, je vais regarder ça ;).

Fig a écrit :On veut bien t'aider, mais on a besoin d'avoir quelques informations... Comment ton monde est modélisé ? Est ce que tu dois éviter beaucoup d'obstacles dynamiques ?
Ce sont des cases de 64*32. en vue isométrique. En soi, ça ne change pas grand chose avec un système classqie si ce n'est qu'on doit pouvoir se déplacer sur un damier isométrique
Si ce sont des obstacle bougeant, je dirai que non, il n'y en a pas ou très peu.
Par contre, il arrive que l'on puisse ajouter un obstacle ou le détruire (ouvrir un enclos/fermer un enclos par exemple).
Cas du A*
Si tu as peu d'obstacles dynamique, tu peux relancer le pathfinding plusieurs fois.
Sinon c'est beaucoup plus compliqué. (double pathfinding, un à l'envers, l'autre à l'endroit, en tenant compte du temps...)
Cas du champs de force
Si c'est une sorte de pacman, tu n'as pas besoin de pathfinding, tu "aimantes" tes ennemis à leur cible simplement.
oui, mais il faudra éviter les obstacle quand même.
Dans tout les cas, le A* basique est très simple, la seule partie un peu ardue, c'est le trie, selon la méthode que tu emploies.
Je cherche justement un exemple très simple de A* basique, mais je n'ai trouvé que des exemples très longs et assez complexes à modifier ^^.
celui que je t'avais fournis ne fonctionne pas ? il peut contourner les obstacles non ?
le résultat en lui-même est super, mais je n'ai pas réussi à le modifier pour l'utiliser :p.
Je voudrais un pathfinding avec des cases en 64*32, et pouvoir l'utiliser en vue isométrique.
Ensuite, je ne sais pas trop comment faire bouger le personnage une fois qu'on clique par exemple ;).

Re: pathfinding

Publié : lun. 02/janv./2012 18:58
par Fig
En somme, tu veux une fonction toute faite pathfinding(x1,y1,x2,y2) qui te retourne une liste de case a parcourir ?
(la taille des cases n'a effectivement pas d'importance... plutôt la largeur de ta carte.)

Re: pathfinding

Publié : mar. 03/janv./2012 15:22
par blendman
ah oui, ce serait carrément pas mal ça :D.

Re: pathfinding

Publié : mar. 03/janv./2012 20:14
par lepiaf31
Bon moi je t'ai fait une fonction qui utilise l'algorithme de dijkstra. Il faut simplement lui donner la carte (avec les couts pour accéder à chaque case, les obstacles ayant une valeur infinie), la case de départ et celle d'arrivée et hop toutes les positions sont renvoyées dans une liste.
Bon je n'explique pas l'algorithme de dijkstra parce que c'est pas simple de l'expliquer à l'écrit (je parle d'experience ^^)
J'ai également fait une petite procédure pour tester et voir si c'est ce que tu cherches.

Ah et je pars du principe qu'on peut se déplacer en diagonale. Si ce n'est pas le cas il faudra bidouiller un peu ;)

Code : Tout sélectionner

;*************************************
;***** PathFinding avec Dijkstra *****
;************ Par lepiaf31 ***********
;*********** Purebasic 4.51 **********
;*************************************
EnableExplicit

#Infinity = -1 ;représente une valeur inifinie

;Structure de coordonnées (x;y)
Structure xy
  x.i ;abscisses
  y.i ;ordonnées
EndStructure

;Compare 2 nombres et renvoi vrai si a <= b (en tenant compte de l'infini)
Procedure smaller(a.i, b.i)
  ProcedureReturn (b=#Infinity Or (a <> #Infinity And a <= b))
EndProcedure

;retourne la somme entre deux nombres (en tenant compte de l'infini)
Procedure sum(a.i, b.i)
  If a = #Infinity Or b = #Infinity
    ProcedureReturn #Infinity
  Else
    ProcedureReturn a + b
  EndIf
EndProcedure
    
;Procedure de recherche du plus court chemin dans un plan en 2D (utilisat l'algorithme de dijkstra en 8-voisinage)
;  plan: tableau contenant le cout pour accéder à chaque case du plan (#Infinity pour un obstacle)
;  sizeX, sizeY: dimensions du plan
;  startCoord, endCoord: coordonnées de départ et d'arrivée du chemeni à trouver
;  result: liste contenant les coordonnées du chemin (liste vide en cas de chemin inexistant)
Procedure dijkstraPathFinding(Array plan.i(2), sizeX.i, sizeY.i, *startCoord.xy, *endCoord.xy, List result.xy())
  Protected x.i, y.i, bestCost.i, *bestCoord, continu.b, cost.i
  Dim pred.xy(sizeX, sizeY) ;coordonnées de la case précédant (x,y) dans le chemin
  Dim cost.i(sizeX, sizeY) ;coût pour accéder à la case (x,y)
  NewList toBeTreated.xy() ;liste des coordonnées à traiter
  
  ;** Initialisation: tous les coups valent l'infini sauf celui de la case de départ **
  For x=0 To sizeX-1
    For y=0 To sizeY-1
      cost(x, y) = #Infinity
      AddElement(toBeTreated())
      toBeTreated()\x = x
      toBeTreated()\y = y
    Next
  Next
  cost(*startCoord\x, *startCoord\y) = 0
  ;****
  
  ;** Début de l'algorithme: on traite toutes les cases non traitées, jusqu'a ce que la case d'arrivée soit traitée **
  continu = #True
  While continu And ListSize(toBeTreated()) > 0
    ;Récupération de la case non traitée ayant le meilleur cout (le plus faible)
    bestCost = #Infinity
    ForEach toBeTreated()
      If smaller(cost(toBeTreated()\x, toBeTreated()\y), bestCost)
        bestCost = cost(toBeTreated()\x, toBeTreated()\y)
        *bestCoord = @toBeTreated()
      EndIf
    Next
    ChangeCurrentElement(toBeTreated(), *bestCoord) ;au se positionne au niveau de l'element qui nous interesse
    
    ;Mise à jour des couts en suivant cet element (on peut se deplacer selon un 8-voisinnage)
    For x = toBeTreated()\x - 1 To toBeTreated()\x + 1
      For y = toBeTreated()\y - 1 To toBeTreated()\y + 1
        If x >= 0 And y >= 0 And x < sizeX And y < sizeY And (x <> toBeTreated()\x Or y <> toBeTreated()\y)
          cost = sum(cost(toBeTreated()\x, toBeTreated()\y), plan(x, y)) ;calcul du coup de la case si on prend ce chemin
          If Not smaller(cost(x, y), cost) ;le nouveau chemin est plus court
            cost(x, y) = cost
            pred(x, y)\x = toBeTreated()\x
            pred(x, y)\y = toBeTreated()\y
          EndIf
        EndIf
      Next
    Next
    
    ;on a fini de traiter la case d'arriver, ce n'est pas la peine de continuer
    If toBeTreated()\x = *endCoord\x And toBeTreated()\y = *endCoord\y 
      continu = #False
    EndIf
    
    DeleteElement(toBeTreated()) ;on a fini de traiter l'element
  Wend
  ;****
  
  ;** Récupération du chemin **
  ClearList(result())
  If cost(*endCoord\x, *endCoord\y) <> #Infinity ;si c'est l'infini, c'est qu'il n'y a pas de chemin
    AddElement(result())
    result()\x = *endCoord\x
    result()\y = *endCoord\y
    While *startCoord\x <> result()\x Or *startCoord\y <> result()\y
      x = pred(result()\x, result()\y)\x
      y = pred(result()\x, result()\y)\y
      ResetList(result())
      AddElement(result())
      result()\x = x
      result()\y = y
    Wend
  EndIf
  ;****
EndProcedure



;***** Tests *****
Procedure showPlan(Array plan.i(2), sizeX.i, sizeY.i, List result.xy())
  Protected window.i, windowWidth.i, windowHeight.i, caseWidth.i, caseHeight.i, x.i, y.i
  
  windowWidth = 300
  windowHeight = 300
  
  window = OpenWindow(#PB_Any, 0, 0, windowWidth, windowHeight, "PathFinding avec Dijkstra", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  If window
    caseWidth = windowWidth / sizeX
    caseHeight = windowHeight / sizeY
    StartDrawing(WindowOutput(window))
    For x=0 To sizeX-1
      For y=0 To sizeY-1
        If plan(x, y) = #Infinity
          Box(x*caseWidth, y*caseHeight, caseWidth, caseHeight, RGB(0,0,0))
        Else
          Box(x*caseWidth, y*caseHeight, caseWidth, caseHeight, RGB(255,255,255))
        EndIf
      Next
    Next
    
    ForEach result()
      Box(result()\x*caseWidth, result()\y*caseHeight, caseWidth, caseHeight, RGB(0,255,0))
    Next
    
    StopDrawing()
  EndIf
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndProcedure

Define nbCol.i, nbLi.i, dep.xy, arr.xy, x.i, y.i

nbCol = 4
nbLi = 4
NewList result.xy()
Dim plan(nbCol, nbLi)

;toutes les cases ont le meme cout
For x=0 To nbCol-1
  For y=0 To nbLi-1
    plan(x,y) = 1
  Next
Next

;on précise certains obstacles:
plan(1, 1) = #Infinity
plan(2, 1) = #infinity

;depart et arrivée
dep\x = 2
dep\y = 0
arr\x = 2
arr\y = 3

dijkstraPathFinding(plan(), nbCol, nbLi, @dep, @arr, result())
showPlan(plan(), nbCol, nbLi, result())

;changons l'arrivée pour voir:
arr\x = 0
arr\y = 2
dijkstraPathFinding(plan(), nbCol, nbLi, @dep, @arr, result())
showPlan(plan(), nbCol, nbLi, result())

Re: pathfinding

Publié : mer. 04/janv./2012 5:57
par SPH
blendman a écrit :Mais je cherche une méthode permettant non pas de trouver le chemin le plus court, mais simplement de contourner un obstacle et donc de trouver un chemin. Ce serait pour mes ennemis par exemple.
Pourquoi ne pas fournir avec la map des coordonnees importantes par lesquelles il faut passer ?

Re: pathfinding

Publié : mer. 04/janv./2012 19:00
par lepiaf31
blendman a écrit :Mais je cherche une méthode permettant non pas de trouver le chemin le plus court, mais simplement de contourner un obstacle et donc de trouver un chemin. Ce serait pour mes ennemis par exemple.
Hé bien si tu trouves le chemin le plus court, tu à trouver un chemin nan ? :P (l'algorithme évite les obstacles c'est écrit ..)

Re: pathfinding

Publié : mer. 04/janv./2012 19:59
par G-Rom
pas besoin de recalculer tout le path, découpe ta map en petite région (ex: 10x10) , chaque portion contient une partie du path, si obstacle dynamique, tu met a jour juste la région concernée.

@+

Re: pathfinding

Publié : mer. 04/janv./2012 20:25
par Cool Dji
Cool Le piaf31,

Dans le temps, j'avais découpé la Map en petites cases hexagonales pour ne pas tronquer les passages en diagonales entre des carrés...

Re: pathfinding

Publié : sam. 07/janv./2012 12:36
par Fig
G-Rom a écrit :pas besoin de recalculer tout le path, découpe ta map en petite région (ex: 10x10) , chaque portion contient une partie du path, si obstacle dynamique, tu met a jour juste la région concernée.

@+
C'est intéressant, mais est ce que ça marche pour un nombre important d'obstacles dynamiques ? (masse d'obstacles dynamiques qui débordent de ton héxagone)
Pour ma part j'utilise la méthode du pathfinding dans une grille de réservation qui tient compte du temps (en fait une hash table avec en clé x,y,t). Ainsi plus aucune collision ni anomalie, ça glisse tout seul.

1- recherche du pathfinding dans une abstraction type HPA* (pour vérifier aussi rapidement si le chemin est possible)
2- recherche dans la première zone d'un path case par case à l'envers (de la fi au début) en tenant compte des obstacles fixes
3- avec les valeurs G de cette recherche j'ai la distance heuristique vrai dont je me sers pour la recherche dans une table de réservation qui tient compte du temps. Si il me manque une valeur G en raison d'un détour important, je résume la recherche 2.

Les obstacles dynamiques sont toujours en pathfinding même à l'arrêt, grâce à un système de priorité, si le path d'une unité passe par le leur, elles se décalent toute seules.

Bref, ça me paraissait compliqué pour le cas de Blendman, sans doute que ta méthode est suffisante :idea:

Articles:
improving collaborative pathfinding using map abstraction

Re: pathfinding

Publié : sam. 07/janv./2012 21:44
par G-Rom
C'est intéressant, mais est ce que ça marche pour un nombre important d'obstacles dynamiques ? (masse d'obstacles dynamiques qui débordent de ton héxagone)
Pour ma part j'utilise la méthode du pathfinding dans une grille de réservation qui tient compte du temps (en fait une hash table avec en clé x,y,t). Ainsi plus aucune collision ni anomalie, ça glisse tout seul.
Ca marche très bien , dans tout les jeux , 2D , 3D , le monde virtuel est toujours fractionner en sous région , quadtree , octree , arbre bsp , etc...
Ta méthode est valable aussi , mais une hash table est consommatrice de ram , sur une très grande map , vaudrais mieux avoir un bon pc ^^^