voila un premier jet, il faut bien garder en mémoire que je n'autorise les déplacements que sur l'horizontale et la verticale pour l'exemple.
Je n'ai pas fini le code. Je pense que je vais ajouter un genre d'algo pour aller en ligne droite entre 2 obstacles, il faut donc détecter les obstacles. Le retour final de la procédure seras une liste des checkpoints (séparés par une case ou plus, pas forcément alignés horizontalement ou verticalement), permettant au perso de se déplacer en ligne droite entre les différents obstacles.
Code : Tout sélectionner
;{ Structure, variables globales, variables du code principal
Structure size_d
cx.d
cy.d
EndStructure
carte.SIZE\cx = 64
carte\cy = 32
w = 600 / 32 * carte\cx
h = 600 / 32 * carte\cy
Dim CarteMap.l(carte\cx - 1, carte\cy - 1)
; explication sur la carte :
; cette carte représente la possibilité de marché ou non sur chaque case.
; on prend comme hypothèse qu'on ne peux se déplacer que horizontalement et verticalement (bien sur ça n'est pas limité à cela, suffit de le coder)
; 1 : obstacle sur la case
; 0 : case libre
; autre chose : aucune signification pour le moment
; on rempli la carte d'objet aléatoires :
For a = 0 To carte\cx * carte\cy / 25
x = Random(carte\cx - 1)
y = Random(carte\cy - 1)
If CarteMap(x, y) = 1
a - 1
Else
CarteMap(x, y) = 1
EndIf
Next
; on ajoute une zone fermée pour tester
For a = 0 To 20
CarteMap(20, a) = 1
CarteMap(a, 20) = 1
Next
NewList Path.POINT()
; position du joueur
joueur.POINT\x = Random(carte\cx - 1)
joueur\y = Random(carte\cy - 1)
CarteMap(joueur\x, joueur\y) = 0
; dimensions des cases
casesize.size_d\cx = (w - 1) / carte\cx
casesize\cy = (h - 1) / carte\cy
; arrive voulue dans le pathfinding (déclaration de la variable)
Define arrive.POINT
;}
;{ procedures
; Global Dim ZCarte(ArraySize(CarteMap(), 1), ArraySize(CarteMap(), 2)) ; DEBUG ONLY
;{ initialisation d'un tableau en dehors de la procedure pour aller plus vite
Global Dim _map_.POINT(3)
_map_(0)\x = 0
_map_(0)\y = -1
_map_(1)\x = -1
_map_(1)\y = 0
_map_(2)\x = 0
_map_(2)\y = 1
_map_(3)\x = 1
_map_(3)\y = 0
Global NewList _tmp_(), NewList _tmp2_()
AddElement(_tmp_())
_tmp_() = 0
AddElement(_tmp_())
_tmp_() = 1
AddElement(_tmp_())
_tmp_() = 2
AddElement(_tmp_())
_tmp_() = 3
;}
Procedure PathFinding(*pos_joueur.POINT, *pos_arrive.POINT, Array carte.l(2), List chemin.POINT())
Protected nb_modif.l, w.l, h.l
; on met à zéro la liste
ClearList(chemin())
w = ArraySize(carte(), 1)
h = ArraySize(carte(), 2)
; on dimensionne la carte de travail
Dim ZCarte(w, h)
; initialisation
ZCarte(*pos_arrive\x, *pos_arrive\y) = 1
; écriture du nombre de pas mini pour arrivé à la case voulue
Repeat
nb_modif = 0
For a = 0 To w
For b = 0 To h
If carte(a, b) <> 1
If a > 0 And ZCarte(a - 1, b) <> 0 And (ZCarte(a - 1, b) + 1 < ZCarte(a, b) Or ZCarte(a, b) = 0) : ZCarte(a, b) = ZCarte(a - 1, b) + 1 : nb_modif + 1 : EndIf
If b > 0 And ZCarte(a, b - 1) <> 0 And (ZCarte(a, b - 1) + 1 < ZCarte(a, b) Or ZCarte(a, b) = 0) : ZCarte(a, b) = ZCarte(a, b - 1) + 1 : nb_modif + 1 : EndIf
If a < w And ZCarte(a + 1, b) <> 0 And (ZCarte(a + 1, b) + 1 < ZCarte(a, b) Or ZCarte(a, b) = 0) : ZCarte(a, b) = ZCarte(a + 1, b) + 1 : nb_modif + 1 : EndIf
If b < h And ZCarte(a, b + 1) <> 0 And (ZCarte(a, b + 1) + 1 < ZCarte(a, b) Or ZCarte(a, b) = 0) : ZCarte(a, b) = ZCarte(a, b + 1) + 1 : nb_modif + 1 : EndIf
EndIf
Next
Next
Until nb_modif = 0
; on en déduie le chemin à prendre en allant toujours dans la case de valeur plus petite que celle actuelle
a = *pos_joueur\x
b = *pos_joueur\y
While ZCarte(a, b) <> 1
CopyList(_tmp_(), _tmp2_())
ok.b = #False
For c = 0 To 3
SelectElement(_tmp2_(), Random(ListSize(_tmp2_()) - 1))
If a + _map_(_tmp2_())\x > 0 And b + _map_(_tmp2_())\y > 0 And a + _map_(_tmp2_())\x < w And b + _map_(_tmp2_())\y < h
If ZCarte(a + _map_(_tmp2_())\x, b + _map_(_tmp2_())\y) <> 0 And ZCarte(a + _map_(_tmp2_())\x, b + _map_(_tmp2_())\y) < ZCarte(a, b)
a + _map_(_tmp2_())\x
b + _map_(_tmp2_())\y
ok = #True
Break
; If a > 0 And ZCarte(a - 1, b) <> 0 And ZCarte(a - 1, b) < ZCarte(a, b)
; a - 1
; ElseIf b > 0 And ZCarte(a, b - 1) <> 0 And ZCarte(a, b - 1) < ZCarte(a, b)
; b - 1
; ElseIf a < w And ZCarte(a + 1, b) <> 0 And ZCarte(a + 1, b) < ZCarte(a, b)
; a + 1
; ElseIf b < h And ZCarte(a, b + 1) <> 0 And ZCarte(a, b + 1) < ZCarte(a, b)
; b + 1
; Else
; coordonnée inacessibles demandée
; ProcedureReturn
EndIf
EndIf
DeleteElement(_tmp2_())
Next
If ok = #False
ProcedureReturn
EndIf
AddElement(chemin())
chemin()\x = a
chemin()\y = b
Wend
EndProcedure
;}
;{ initialisation
If InitSprite() = 0 Or InitKeyboard() = 0
End
EndIf
;}
;{ ouverture de la fenetre
If OpenWindow(0, 0, 0, w, h, "PathFinding sur une carte", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
If OpenWindowedScreen(WindowID(0), 0, 0, w, h, 0, 0, 0)
Else
End
EndIf
Else
End
EndIf
;}
;{ boucle principale
Repeat
event = WaitWindowEvent(100)
ExamineKeyboard()
;{ clavier
If KeyboardReleased(#PB_Key_Escape) : event = #PB_Event_CloseWindow : EndIf
;}
;{ evenement souris
If event = #WM_LBUTTONDOWN
; je laisse la possibilité de mettre l'arrivé sur un obstacle pour voir comment réagit l'algo
arrive\x = Round(WindowMouseX(0) / casesize\cx, #PB_Round_Down)
arrive\y = Round(WindowMouseY(0) / casesize\cy, #PB_Round_Down)
If Not (arrive\x < 0 Or arrive\x > carte\cx Or arrive\y < 0 Or arrive\y > carte\cy)
PathFinding(joueur, arrive, CarteMap(), Path())
EndIf
EndIf
;}
;{ graphismes
ClearScreen(0)
If StartDrawing(ScreenOutput())
; DrawingMode(#PB_2DDrawing_Transparent)
Line(carte\cx * casesize\cx, 0, 1, h, #White)
Line(0, carte\cy * casesize\cy, w, 1, #White)
For a = 0 To carte\cx - 1
Line(a * casesize\cx, 0, 1, h, #White)
For b = 0 To carte\cy - 1
If a = 0 : Line(0, b * casesize\cy, w, 1, #White) : EndIf
If CarteMap(a, b) = 1
; dessin obstacle
Box(a * casesize\cx, b * casesize\cy, Round(casesize\cx, #PB_Round_Up), Round(casesize\cy, #PB_Round_Up), #Gray)
EndIf
; DrawText(a * casesize\cx + 1, b * casesize\cy + 1, Str(ZCarte(a, b))) ; DEBUG ONLY
Next
Next
Circle((joueur\x + 0.5) * casesize\cx, (joueur\y + 0.5) * casesize\cy, casesize\cx / 2, #Red)
Circle((arrive\x + 0.5) * casesize\cx, (arrive\y + 0.5) * casesize\cy, casesize\cx / 2, #Blue)
ForEach Path()
Circle((path()\x + 0.5) * casesize\cx, (path()\y + 0.5) * casesize\cy, casesize\cx / 5, #Yellow)
Next
StopDrawing()
EndIf
FlipBuffers()
;}
Until event = #PB_Event_CloseWindow
;}
End