j'ai posté ce code au départ pour Blendman et graph100 dans un sujet sur le chargement des sprites qui a un peu dévié. Comme Je pense que ce code pourrait intéressé d'autre personne je le met ici pour plus de visibilité.
Code : Tout sélectionner
Procedure CatmullRomSpline(t.f,*result.POINT,*p0.Point,*p1.Point,*p2.point,*p3.point)
t2.f = t * t
t3.f = t2 * t
*result\x= 0.5 * ( ( 2.0 * *p1\x ) + ( -*p0\x + *p2\x ) * t + ( 2.0 * *p0\x - 5.0 * *p1\x + 4 * *p2\x - *p3\x ) * t2 + ( -*p0\x + 3.0 * *p1\x - 3.0 * *p2\x + *p3\x ) * t3 )
*result\y= 0.5 * ( ( 2.0 * *p1\y ) + ( -*p0\y + *p2\y ) * t + ( 2.0 * *p0\y - 5.0 * *p1\y + 4 * *p2\y - *p3\y ) * t2 + ( -*p0\y + 3.0 * *p1\y - 3.0 * *p2\y + *p3\y ) * t3 )
EndProcedure
#tileWidth=48; taille d'un tile
;-Le personnage
Structure chara
;position acutel du personnage (coordonée reel en pixel)
worldPixelX.l
worldPixelY.l
;position ou veut aller le personnage (coordonée reel en pixel)
ToWorldPixelX.l
ToWorldPixelY.l
pathSize.l;Nombre de case dans le chemin
num.l ; notre prosition sur le chemin
startTime.l ; gestion du temps du deplacement
startWorldPixelX.l; pour le deplacement j'ai besoin de mémorisé le point de depart
startWorldPixelY.l
EndStructure
chara.chara
;je initialise la position de mon personnage
chara\worldPixelX=10
chara\worldPixelY=10
;je fais comme si on voulait aller a un autre endroit
;c'est pas tres loin du point de depart, mais le faux pathfinding
;un peu plus loin fera un detour
chara\ToWorldPixelX=10
chara\ToWorldPixelY=42
;-Le chemin
Structure chemin
x.l
y.l
EndStructure
NewList chemin.chemin()
If InitSprite() = 0
MessageRequester("Error", "Can't open screen & sprite enviroment!", 0)
End
EndIf
If OpenWindow(0, 0, 0, 800, 600, "A screen in a window...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateStatusBar(0, WindowID(0))
AddStatusBarField(320)
If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 1, 0, 20)
Repeat
; It's very important to process all the events remaining in the queue at each frame
;
Repeat
Event = WaitWindowEvent(10)
If Event = #PB_Event_CloseWindow
End
EndIf
Until Event = 0
;-Deplacement
;en gros si mon point de depart et d'arrivé est différent et qu'on a pas de chemin faut trouver un chemin
If (chara\ToWorldPixelX<>chara\worldPixelX Or chara\ToWorldPixelY<>chara\worldPixelY) And chara\pathSize=0
;ici on utilise un pathfinding normalement
tileX=Int(chara\worldPixelX/#tileWidth)
tileY=Int(chara\worldPixelY/#tileWidth)
toTileX=Int(chara\ToWorldPixelX/#tileWidth)
toTileY=Int(chara\ToWorldPixelY/#tileWidth)
;mais ici c'est pas le pathfinding qui nous interesse donc voici un chemin au format list
AddElement(chemin()):chemin()\x=1:chemin()\y=0
AddElement(chemin()):chemin()\x=1:chemin()\y=1
AddElement(chemin()):chemin()\x=2:chemin()\y=1
AddElement(chemin()):chemin()\x=3:chemin()\y=1
AddElement(chemin()):chemin()\x=4:chemin()\y=1
AddElement(chemin()):chemin()\x=5:chemin()\y=2
AddElement(chemin()):chemin()\x=6:chemin()\y=3
AddElement(chemin()):chemin()\x=6:chemin()\y=4
AddElement(chemin()):chemin()\x=6:chemin()\y=5
AddElement(chemin()):chemin()\x=6:chemin()\y=6
AddElement(chemin()):chemin()\x=7:chemin()\y=6
AddElement(chemin()):chemin()\x=8:chemin()\y=6
AddElement(chemin()):chemin()\x=9:chemin()\y=7
AddElement(chemin()):chemin()\x=9:chemin()\y=8
AddElement(chemin()):chemin()\x=8:chemin()\y=9
AddElement(chemin()):chemin()\x=7:chemin()\y=10
AddElement(chemin()):chemin()\x=6:chemin()\y=10
AddElement(chemin()):chemin()\x=5:chemin()\y=10
AddElement(chemin()):chemin()\x=5:chemin()\y=9
AddElement(chemin()):chemin()\x=4:chemin()\y=8
AddElement(chemin()):chemin()\x=3:chemin()\y=7
AddElement(chemin()):chemin()\x=3:chemin()\y=6
AddElement(chemin()):chemin()\x=3:chemin()\y=5
AddElement(chemin()):chemin()\x=3:chemin()\y=4
AddElement(chemin()):chemin()\x=3:chemin()\y=3
AddElement(chemin()):chemin()\x=2:chemin()\y=2
AddElement(chemin()):chemin()\x=1:chemin()\y=1
AddElement(chemin()):chemin()\x=0:chemin()\y=1
chara\pathSize=ListSize(chemin()) ;le nombre de case pour le deplacement
chara\startTime=ElapsedMilliseconds() ;on initialise le temps pour le debut du deplacement
chara\num=-1 ; j'initialise mon "pointeur" dans le chemin établit part le pathfinding
chara\startWorldPixelX=chara\worldPixelX ; et je memorise mon point de depart
chara\startWorldPixelY=chara\worldPixelY ;
;End
EndIf
;si on a un chemin alors hop on avance
If chara\pathSize>0
t.f=(ElapsedMilliseconds()-chara\startTime)/1000 ;t doit varier de 0 a 1.0 étant le depart d'une case, le 1 etant l'arrivé de la case suivante
move=1 ;on doit se depalcer
;si on arrive a la case suivante
If t>=1
t=1
If chara\num>chara\pathSize-2 ;là on est arrivé
Debug "FIN";
;j'efface mon chemin effectué
ClearList(chemin())
move=0 ;plus besoin de bougé
chara\pathSize=0
chara\num=0
chara\worldPixelX=chara\ToWorldPixelX ;on est bien arrivé au point qu'on voulait
chara\worldPixelY=chara\ToWorldPixelY
EndIf
chara\startTime=ElapsedMilliseconds(): ;je memorise le temps
EndIf
EndIf
If move=1 ; si on doit se depalcer
Dim p.point(3) ;et pour faire ma route d'un tile a un autre j'ai besoin de connaitre 4 points (catmull rom)
For z=0 To 3
num=chara\num+z-1
If num<0:
num=-1
EndIf
If num>chara\pathSize-1
num=chara\pathSize-1
EndIf
Select num
Case -1
p(z)\x=chara\startWorldPixelX
p(z)\y=chara\startWorldPixelY
Case chara\pathSize-1
p(z)\x= chara\ToWorldPixelX
p(z)\y= chara\ToWorldPixelY
Default
SelectElement(chemin(),num)
p(z)\x=chemin()\x*#tileWidth+#tileWidth/2
p(z)\y=chemin()\y*#tileWidth+#tileWidth/2
EndSelect
Next
result.point
CatmullRomSpline(t,result,p(0),p(1),p(2),p(3))
If t>=1 ;On est arrivé a la nouvelle case
chara\num+1:;on avance d'une case sur mon chemin
EndIf
;les nouvelles coordonées de notre personnage
chara\worldPixelX=result\x
chara\worldPixelY=result\y
EndIf
FlipBuffers()
ClearScreen(0) ; A blue background
StartDrawing(ScreenOutput())
For x=1 To 20
LineXY(x*#tileWidth,0,x*#tileWidth,600,#White)
Next
For y=0 To 20
LineXY(0,y*#tileWidth,800,y*#tileWidth,#White)
Next
ForEach chemin()
Box(chemin()\x*#tileWidth,chemin()\y*#tileWidth,#tileWidth,#tileWidth,RGB(50,50,50))
Next
Circle(chara\worldPixelX,chara\worldPixelY,5,#Red)
StopDrawing()
ForEver
Else
MessageRequester("Error", "Can't open windowed screen!", 0)
EndIf
EndIf