pathfinding

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

pathfinding

Message 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 :)
dayvid
Messages : 1242
Inscription : mer. 11/nov./2009 18:17
Localisation : Poitiers (Vienne)

Re: pathfinding

Message 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
La vie, C'est comme, Une boitte, De startis, On en voie, De toutes, Les couleurs !

Mon forum http://purebasic.forumphp3.com/index.php
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: pathfinding

Message 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.
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: pathfinding

Message 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.
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: pathfinding

Message par graph100 »

celui que je t'avais fournis ne fonctionne pas ? il peut contourner les obstacles non ?
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: pathfinding

Message 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 ;).
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: pathfinding

Message 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.)
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: pathfinding

Message par blendman »

ah oui, ce serait carrément pas mal ça :D.
lepiaf31
Messages : 510
Inscription : dim. 25/mars/2007 13:44
Localisation : Toulouse, France
Contact :

Re: pathfinding

Message 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())
Avatar de l’utilisateur
SPH
Messages : 4947
Inscription : mer. 09/nov./2005 9:53

Re: pathfinding

Message 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 ?

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
lepiaf31
Messages : 510
Inscription : dim. 25/mars/2007 13:44
Localisation : Toulouse, France
Contact :

Re: pathfinding

Message 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 ..)
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: pathfinding

Message 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.

@+
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: pathfinding

Message 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...
Only PureBasic makes it possible
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: pathfinding

Message 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
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: pathfinding

Message 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 ^^^
Répondre