Page 1 of 1

movement with CatmullRom spline on a Map

Posted: Tue Jun 28, 2011 8:00 pm
by thyphoon
Hello,

excuse me for my bad english. I would like to share with you my code to move on map with Catmullrom spline
I hope you will like this code
regards

Code: Select all

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
;-Characters
Structure chara
  ;reel chara coord
  worldPixelX.l
  worldPixelY.l
  ;the target where you want to go
  ToWorldPixelX.l
  ToWorldPixelY.l
 
  pathSize.l;tile number in path
  num.l ; pointer on path
  startTime.l ; time to move
  startWorldPixelX.l; to save the start coord
  startWorldPixelY.l
EndStructure

chara.chara
;init characters position
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 path
Structure path
  x.l
  y.l
EndStructure

NewList path.path()


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
      ;if current coord <> targ pos you must found a path
      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)
        ;pathfinding simulation
        AddElement(path()):path()\x=1:path()\y=0
        AddElement(path()):path()\x=1:path()\y=1
        AddElement(path()):path()\x=2:path()\y=1
        AddElement(path()):path()\x=3:path()\y=1
        AddElement(path()):path()\x=4:path()\y=1
        AddElement(path()):path()\x=5:path()\y=2
        AddElement(path()):path()\x=6:path()\y=3
        AddElement(path()):path()\x=6:path()\y=4
        AddElement(path()):path()\x=6:path()\y=5
        AddElement(path()):path()\x=6:path()\y=6
        AddElement(path()):path()\x=7:path()\y=6
        AddElement(path()):path()\x=8:path()\y=6
        AddElement(path()):path()\x=9:path()\y=7
        AddElement(path()):path()\x=9:path()\y=8
        AddElement(path()):path()\x=8:path()\y=9
        AddElement(path()):path()\x=7:path()\y=10
        AddElement(path()):path()\x=6:path()\y=10
        AddElement(path()):path()\x=5:path()\y=10
        AddElement(path()):path()\x=5:path()\y=9
        AddElement(path()):path()\x=4:path()\y=8
        AddElement(path()):path()\x=3:path()\y=7
        AddElement(path()):path()\x=3:path()\y=6
        AddElement(path()):path()\x=3:path()\y=5
        AddElement(path()):path()\x=3:path()\y=4
        AddElement(path()):path()\x=3:path()\y=3
        AddElement(path()):path()\x=2:path()\y=2
        AddElement(path()):path()\x=1:path()\y=1
        AddElement(path()):path()\x=0:path()\y=1
        chara\pathSize=ListSize(path()) ;tile number in the path
        chara\startTime=ElapsedMilliseconds() ;time to move
        chara\num=-1 ;    init my path pointer
        chara\startWorldPixelX=chara\worldPixelX ; save the start coord
        chara\startWorldPixelY=chara\worldPixelY ;
        ;End
      EndIf   
     
     
      ;si on a un path alors hop on avance
      If chara\pathSize>0
       
        t.f=(ElapsedMilliseconds()-chara\startTime)/1000 ;t= 0 last tile => 1  next tile
       
        move=1 ;we move
        ;if next tile
        If t>=1
          t=1
         
          If chara\num>chara\pathSize-2 ;the end
            Debug "end";
            ;clear the path
            ClearList(path())
            move=0 ;no move
            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  ; if we must move
        Dim p.point(3) ;to know position on a catmull rom, i must know 4 points
        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(path(),num)
              p(z)\x=path()\x*#tileWidth+#tileWidth/2
              p(z)\y=path()\y*#tileWidth+#tileWidth/2
          EndSelect
        Next
        result.point
       
        CatmullRomSpline(t,result,p(0),p(1),p(2),p(3))
       
        If t>=1 ;if next tile
          chara\num+1:;next path tile
        EndIf

        ;new coord to to caracters
        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 path()
        Box(path()\x*#tileWidth,path()\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

Re: movement with CatmullRom spline on a Map

Posted: Wed Jun 29, 2011 2:35 pm
by IdeasVacuum
Completely different genre of programming to mine but that looks very clever indeed!

Nice work and thank you for sharing 8)

Re: movement with CatmullRom spline on a Map

Posted: Wed Jun 29, 2011 2:45 pm
by rsts
Very nice.

Not to worry about your English. The code speaks for itself :)

Thanks for sharing.

cheers