deplacement dans une map tout en souplesse

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

deplacement dans une map tout en souplesse

Message par Thyphoon »

Voici un code qui montre la façon dont je deplace un perso dans une map en suivant un chemin.

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

Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: deplacement dans une map tout en souplesse

Message par Kwai chang caine »

Comme dab, j'ai pas compris le coté pédagogique.
Mais je peux dire que c'est beau

Merci Typhoon 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: deplacement dans une map tout en souplesse

Message par Thyphoon »

Kwai chang caine a écrit :Comme dab, j'ai pas compris le coté pédagogique.
j'ai essayé de commenté au maximum mon code pour comprendre le fonctionnement.
mais sil il y a des questions n'hesitez pas !
Kwai chang caine a écrit : Mais je peux dire que c'est beau
Merci Typhoon 8)
De rien :mrgreen:
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Re: deplacement dans une map tout en souplesse

Message par Huitbit »

Joli, joli :D !
Kwai chang caine a écrit :Comme dab, j'ai pas compris le coté pédagogique.
Au déplacement de Pac Man tu dois comparer jeune Padawan :lol: :lol:

Hasta la vista !
Elevé au MSX !
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: deplacement dans une map tout en souplesse

Message par kelebrindae »

Ah oui, très joli! Et très utile, aussi. Merci beaucoup! :D
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: deplacement dans une map tout en souplesse

Message par Thyphoon »

Huitbit a écrit :Joli, joli :D ! !
Merci ! :D
kelebrindae a écrit :Ah oui, très joli! Et très utile, aussi. Merci beaucoup! :D
de rien :P
Répondre