Moving Sprite along predetermined path

Advanced game related topics
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Moving Sprite along predetermined path

Post by Fluid Byte »

I'm currently working an a game engine specialised in shoot 'em ups. Now I got to the point where I have to think about the creation of advanced enemy wave patterns. Certainly there's a lot you can do with sine/cosine but it has it's limits. What I'm looking for is way to specify an animation path for a sprite like you create paths in graphics programs similar to Adobe Photoshop. This should include the rather complex usage and manipulation of bezier curves.

I'm totally clueless where to start and wonder if there's same kind of engine to use or a specific, programmatic concept to apply to this particular problem.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Moving Sprite along predetermined path

Post by luis »

There are a lot of books talking specifically about AI in games and many of them include a chapter on path planning, path following or whatever. Bezier lines, as you suggest can be useful for some class of problems.
In many simpler cases, relative movement specifications (from current pos up at vel 1.0, left at vel 0.5) can be stored in a simple array and tied to the passage of time.

Maybe here you can find something to help you build a general idea, and then look specifically for something more relevant to your case:

http://www.red3d.com/cwr/steer/
"Have you tried turning it off and on again ?"
A little PureBasic review
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: Moving Sprite along predetermined path

Post by gnasen »

here is a little start, maybe it helps you a bit:

Code: Select all

EnableExplicit

InitSprite()

#steps = 50

Structure s_point
  x.f
  y.f
EndStructure

Procedure drawBlezier(Array in.s_point(1),c.i=-1)
  
  Protected count.i = ArraySize(in(),1)
  Protected a.i,b.i
  Protected Dim new.s_point(count-1)
  Protected cancel.i
  
  If c=-1
    c=0
    cancel = #False
  Else
    cancel = #true
  EndIf
  
  For a=c To #steps
    
    For b=0 To count-1
      
      new(b)\x = in(b)\x + (in(b+1)\x-in(b)\x) * a / #steps
      new(b)\y = in(b)\y + (in(b+1)\y-in(b)\y) * a / #steps
      
    Next
    
    If count = 1
      Plot(new(0)\x,new(0)\y,$FFFFFF)
    Else
      drawBlezier(new(),a)
    EndIf
    
    If cancel
      Break
    EndIf
    
  Next

EndProcedure

Dim points.s_point(4)

points(0)\x = 50
points(0)\y = 440

points(1)\x = 100
points(1)\y = 100

points(2)\x = 150
points(2)\y = 40

points(3)\x = 220
points(3)\y = 80

points(4)\x = 400
points(4)\y = 50

OpenWindow(0,0,0,800,600,"blezier",#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0),0,0,800,600,0,0,0)

Define eventID.i

Repeat
  Repeat
    eventID = WindowEvent()
    If eventID = #PB_Event_CloseWindow
      End
    EndIf
  Until eventID = 0
  ClearScreen(0)
  
  StartDrawing(ScreenOutput())
    drawBlezier(points())
    Define a.i
    For a=0 To 4
      Plot(points(a)\x,points(a)\y,$0000FF)
    Next
  StopDrawing()
    
  FlipBuffers()
ForEver
it is just the standard blezier curve and makes this smooth path between different points
pb 5.11
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Re: Moving Sprite along predetermined path

Post by Fluid Byte »

luis wrote:In many simpler cases, relative movement specifications (from current pos up at vel 1.0, left at vel 0.5) can be stored in a simple array and tied to the passage of time.
You mean something like this?

Code: Select all

InitSprite() : InitKeyboard()

OpenWindow(0,0,0,640,480,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)

Structure POSITION
	XV.f
	YV.f
	Frame.w
EndStructure

X.f = 40
Y.f = 40
XV.f = 0
YV.f = 0

Global NewList pos.POSITION()

Procedure AddMarker(XV.f,YV.f,Frame)
	AddElement(pos())
	pos()\XV = XV
	pos()\YV = YV
	pos()\Frame = Frame
EndProcedure

AddMarker(0.25,1,60 * 1)
AddMarker(0.5,1,60 * 2)
AddMarker(0.75,1,60 * 3)
AddMarker(1,1,60 * 4)
AddMarker(1,0.5,60 * 5)
AddMarker(1,0.25,60 * 6)
AddMarker(0.75,-0.5,60 * 7)
AddMarker(0.5,-0.75,60 * 8)
AddMarker(-0.25,-1,60 * 9)
AddMarker(-1,-0.5,60 * 10)
AddMarker(-0.5,-2,60 * 11)

Repeat
	Repeat
		EventID = WindowEvent()	
		Select EventID
			Case #PB_Event_CloseWindow : End 
		EndSelect
	Until EventID = 0
	
	ExamineKeyboard()	
		
	ForEach pos()		
		If pos()\Frame = TotalFrames
			XV = pos()\XV : YV = pos()\YV
			DeleteElement(pos())
		EndIf		
	Next
	
	TotalFrames + 1
	
	ClearScreen(0)
	StartDrawing(ScreenOutput())
	X + XV
	Y + YV
	Ellipse(X,Y,32,32,#Red)
	StopDrawing()
	FlipBuffers()
	
	Delay(1)
Until KeyboardPushed(#PB_Key_Escape)
luis wrote:Maybe here you can find something to help you build a general idea, and then look specifically for something more relevant to your case: http://www.red3d.com/cwr/steer/
Certainly very good stuff my time on this earth is limited :P

@gnasen:
Looks promising but I have no clue what's going on especially since it uses recursion.

Though I have a question ...

Shouldn't be the path exactly aligned on the waypoints?

Image
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: Moving Sprite along predetermined path

Post by gnasen »

By the standard bezier curve, it normally wont go through all points. You can see here, how they are calculated:
http://en.wikipedia.org/wiki/B%C3%A9zier_curve

If they should pass through all points, it wouldnt be that simple. I will think about it ;)
pb 5.11
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Re: Moving Sprite along predetermined path

Post by Fluid Byte »

I will try to read and understand it but expect no miracles! :o
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: Moving Sprite along predetermined path

Post by gnasen »

Here is another way to do it:

Code: Select all

EnableExplicit

InitSprite()

Structure s_point
  x.f
  y.f
EndStructure
Procedure drawCurve(Array in.s_point(1))
  
  Protected size.i = ArraySize(in())
  Protected Dim matrix.f(size+1,size)
  Protected x.i,y.i,z.i
  Protected factor.f, value.f
  Protected Dim polynom.f(size)
  
  ;/ create system of linear equations
  For x=0 To size
    For y=0 To size
      matrix(x,y) = Pow(in(y)\x,x)
    Next
  Next
  
  For y=0 To size
    matrix(size+1,y) = in(y)\y
  Next
 
  ;/ solve system
  For x=0 To size-1
    For y=x+1 To size
      factor = matrix(x,y) / matrix(x,x)
      For z=0 To size+1
        matrix(z,y) = matrix(z,y) - matrix(z,x) * factor
      Next 
    Next
  Next
  
  For y=0 To size
    For z=0 To y-1
      matrix(size+1,size-y) = matrix(size+1,size-y) - matrix(size-z,size-y) * polynom(size-z)
    Next
    polynom(size-y) = matrix(size+1,size-y) / matrix(size-y,size-y)
  Next

  ;/ draw Polynom
  For x=in(0)\x To in(size)\x
    value = 0
    For y=0 To size
      value + polynom(y) * Pow(x,y)
    Next
    If value >= 0 And value <= 600
      Plot(x,value,$FFFFFF)
    EndIf
  Next
  
EndProcedure

Dim points.s_point(4)

points(0)\x = 30
points(0)\y = 40

points(1)\x = 70
points(1)\y = 90

points(2)\x = 120
points(2)\y = 50

points(3)\x = 220
points(3)\y = 280

points(4)\x = 300
points(4)\y = 50

OpenWindow(0,0,0,800,600,"blezier",#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0),0,0,800,600,0,0,0)

Define eventID.i

Repeat
  Repeat
    eventID = WindowEvent()
    If eventID = #PB_Event_CloseWindow
      End
    EndIf
  Until eventID = 0
  ClearScreen(0)
  
  StartDrawing(ScreenOutput())
    drawCurve(points())
    Define a.i
    For a=0 To 4
      Box(points(a)\x-1,points(a)\y-1,3,3,$0000FF)
    Next
  StopDrawing()
  
  FlipBuffers()
ForEver
This is an analytic solving with a polynomial. The Idea is to create a system of linear equations and solve them. The result is a polynom of n-th order. The problem is, that polynoms behave a very special way and get very fast "unstable" for a degree of maybe 5 or higher. So this may be a solution for some special cases. But I'm very interested in this problem, so give some more time to think about it ;)
pb 5.11
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: Moving Sprite along predetermined path

Post by gnasen »

And another one, I like this the most until now:
Image

Code: Select all

EnableExplicit

InitSprite()

Structure s_point
  x.f
  y.f
EndStructure
Procedure solve(Array matrix.f(2), Array polynom.f(1))
  
  Protected x.i,y.i,z.i,factor.f
  Protected size.i = ArraySize(matrix(),2)
  
  For x=0 To size-1
    For y=x+1 To size
      If matrix(x,y) <> 0
        factor = matrix(x,y) / matrix(x,x)
        For z=0 To size+1
          matrix(z,y) = matrix(z,y) - matrix(z,x) * factor
        Next 
      EndIf
    Next
  Next
  
  For y=0 To size
    For z=0 To y-1
      matrix(size+1,size-y) = matrix(size+1,size-y) - matrix(size-z,size-y) * polynom(size-z)
    Next
    polynom(size-y) = matrix(size+1,size-y) / matrix(size-y,size-y)
  Next
  
EndProcedure
Procedure drawSpline(Array in.s_point(1))
  
  Protected size.i = ArraySize(in())
  Protected Dim matrix.f(size*3,size*3-1)
  Protected Dim polynom.f(size*3-1)
  Protected x.i,y.i,z.i
  Protected value.f

  ;/ create system of linear equations
  For z=0 To size-1
    matrix(z*3+0, 3*z+0)    = 1
    matrix(z*3+1, 3*z+0)    = in(z)\x
    matrix(z*3+2, 3*z+0)    = in(z)\x*in(z)\x
    matrix(size*3,3*z+0)   = in(z)\y
    matrix(z*3+0, 3*z+1)    = 1
    matrix(z*3+1, 3*z+1)    = in(z+1)\x
    matrix(z*3+2, 3*z+1)    = in(z+1)\x*in(z+1)\x
    matrix(size*3,3*z+1)   = in(z+1)\y
    If z <= size-2
      matrix(z*3+0, 3*z+2)    = 0
      matrix(z*3+1, 3*z+2)    = 1
      matrix(z*3+2, 3*z+2)    = 2*in(z+1)\x
      matrix(z*3+3, 3*z+2)    = 0
      matrix(z*3+4, 3*z+2)    = -1
      matrix(z*3+5, 3*z+2)    = -2*in(z+1)\x
    EndIf
  Next
  matrix(2,size*3-1) = 1
  
  ;/ solve system
  solve(matrix(),polynom())
  
  ;/ draw
  For z=0 To size-1
    For x=in(z)\x To in(z+1)\x
      
      value=0
      For y=0 To 2
        value + polynom(z*3+y) * Pow(x,y)
      Next
      If value >= 0 And value <= 600
        Plot(x,value,$FFFFFF)
      EndIf
      
    Next
  Next

EndProcedure

Dim points.s_point(10)

points(0)\x = 50
points(0)\y = 480
points(1)\x = 100
points(1)\y = 140
points(2)\x = 150
points(2)\y = 80
points(3)\x = 200
points(3)\y = 120
points(4)\x = 250
points(4)\y = 90
points(5)\x = 300
points(5)\y = 140
points(6)\x = 350
points(6)\y = 100
points(7)\x = 400
points(7)\y = 320
points(8)\x = 450
points(8)\y = 440
points(9)\x = 500
points(9)\y = 480
points(10)\x = 550
points(10)\y = 420

OpenWindow(0,0,0,800,600,"blezier",#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0),0,0,800,600,0,0,0)

Define eventID.i

Repeat
  Repeat
    eventID = WindowEvent()
    If eventID = #PB_Event_CloseWindow
      End
    EndIf
  Until eventID = 0
  ClearScreen(0)
  
  StartDrawing(ScreenOutput())
    drawSpline(points())
    Define a.i
    For a=0 To 10
      Box(points(a)\x-1,points(a)\y-1,3,3,$0000FF)
    Next
  StopDrawing()
  
  FlipBuffers()
ForEver
This is a quadratic spline interpolation. If someone is interested in this, I could create a more usable snippet for the tricks'n'tipps section.
To be honest I would really like to know now, how a cubic or higher interpolation would look like.
Edit: I think I could also replace the function as a result with a curve (you know, loopings etc allowed), maybe I will have a look at this.
pb 5.11
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: Moving Sprite along predetermined path

Post by gnasen »

Hey, this makes fun, next one (sry for the monologue ;) )
Image

Code: Select all

EnableExplicit

InitSprite()

Structure s_point
  x.f
  y.f
EndStructure

Procedure solve(Array matrix.f(2), Array polynom.f(1))
  
  Protected x.i,y.i,z.i,factor.f
  Protected size.i = ArraySize(matrix(),2)
  
  For x=0 To size-1
    For y=x+1 To size
      If matrix(x,y) <> 0
        factor = matrix(x,y) / matrix(x,x)
        For z=0 To size+1
          matrix(z,y) = matrix(z,y) - matrix(z,x) * factor
        Next 
      EndIf
    Next
  Next
  
  For y=0 To size
    For z=0 To y-1
      matrix(size+1,size-y) = matrix(size+1,size-y) - matrix(size-z,size-y) * polynom(size-z)
    Next
    polynom(size-y) = matrix(size+1,size-y) / matrix(size-y,size-y)
  Next
  
EndProcedure
Procedure spline(Array in.f(1), Array polynom.f(1))
  
  Protected size.i = ArraySize(in())
  Protected Dim matrix.f(size*3,size*3-1)
  Protected Dim polynom.f(size*3-1)
  Protected x.i,y.i,z.i
  Protected value.f
  
  ;/ create system of linear equations
  For z=0 To size-1
    matrix(z*3+0, 3*z+0)    = 1
    matrix(z*3+1, 3*z+0)    = z
    matrix(z*3+2, 3*z+0)    = z*z
    matrix(size*3,3*z+0)    = in(z)
    matrix(z*3+0, 3*z+1)    = 1
    matrix(z*3+1, 3*z+1)    = z+1
    matrix(z*3+2, 3*z+1)    = (z+1)*(z+1)
    matrix(size*3,3*z+1)    = in(z+1)
    If z <= size-2
      matrix(z*3+0, 3*z+2)    = 0
      matrix(z*3+1, 3*z+2)    = 1
      matrix(z*3+2, 3*z+2)    = 2*(z+1)
      matrix(z*3+3, 3*z+2)    = 0
      matrix(z*3+4, 3*z+2)    = -1
      matrix(z*3+5, 3*z+2)    = -2*(z+1)
    EndIf
  Next
  matrix(2,size*3-1) = 1
  
  ;/ solve system
  solve(matrix(),polynom())
  
EndProcedure
Procedure createPath(Array in.s_point(1))
  
  Protected size.i = ArraySize(in())
  Protected Dim xpath.f(size)
  Protected Dim ypath.f(size)
  Protected Dim xpoly.f(size*3-1)
  Protected Dim ypoly.f(size*3-1)
  Protected z.i
  
  For z=0 To size
    xpath(z) = in(z)\x
    ypath(z) = in(z)\y
  Next

  spline(xpath(),xpoly())
  spline(ypath(),ypoly())
  
  ;/ draw
  
  Protected a.i,b.i,c.i
  Protected cur.f,valueX.f,valueY.f
  
  For a=0 To size-1
    For c=0 To 30
    
      cur = a+c/31
      
      valueX=0
      valueY=0
      For b=0 To 2
        valueX + xpoly(a*3+b) * Pow(cur,b)
        valueY + ypoly(a*3+b) * Pow(cur,b)
      Next
      
      If valueX >= 0 And valueX <= 800
        If valueY >= 0 And valueY <= 600
          Plot(valueX,valueY,$FFFFFF)
        EndIf
      EndIf
      
    Next
  Next
  
EndProcedure

;-------------------- TEST --------------------

Dim points.s_point(10)

points(0)\x = 50
points(0)\y = 480
points(1)\x = 100
points(1)\y = 140
points(2)\x = 50
points(2)\y = 180
points(3)\x = 200
points(3)\y = 220
points(4)\x = 250
points(4)\y = 90
points(5)\x = 300
points(5)\y = 140
points(6)\x = 500
points(6)\y = 100
points(7)\x = 400
points(7)\y = 320
points(8)\x = 450
points(8)\y = 440
points(9)\x = 500
points(9)\y = 480
points(10)\x = 100
points(10)\y = 480


OpenWindow(0,0,0,800,600,"blezier",#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0),0,0,800,600,0,0,0)

Define eventID.i

Repeat
  Repeat
    eventID = WindowEvent()
    If eventID = #PB_Event_CloseWindow
      End
    EndIf
  Until eventID = 0
  ClearScreen(0)
  
  StartDrawing(ScreenOutput())
    createPath(points())
    Define a.i
    For a=0 To 10
      Box(points(a)\x-1,points(a)\y-1,3,3,$0000FF)
    Next
  StopDrawing()
  
  FlipBuffers()
ForEver
Now with curves. Quadratic interpolation seems to be much more stable then the polynom interpolation. Anyway its unstable in some cases, next logic step would be to increase the spline interpolation to cubic or higher. I will try to make it dynamic chooseable. However I think I may have to improve the solve routine for higher orders.
pb 5.11
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Re: Moving Sprite along predetermined path

Post by Fluid Byte »

Seriously, I have no idea what you are doing and merely understand what's going on 8)

Though, I have another question. Well, it have been two but I managed to actually display a sprite with your previous example on my own.

Code: Select all

EnableExplicit

InitSprite()

OpenWindow(0,0,0,800,600,"blezier",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,800,600,0,0,0)

LoadSprite(0,#PB_Compiler_Home + "Examples\Sources\Data\Geebee2.bmp")
TransparentSpriteColor(0,RGB(255,0,255))

Structure s_point
	x.f
	y.f
EndStructure

Global NewList p.s_point()
NewList tmp.s_point()

Procedure solve(Array matrix.f(2), Array polynom.f(1))	
	Protected x.i,y.i,z.i,factor.f
	Protected size.i = ArraySize(matrix(),2)
	
	For x=0 To size-1
		For y=x+1 To size
			If matrix(x,y) <> 0
				factor = matrix(x,y) / matrix(x,x)
				For z=0 To size+1
					matrix(z,y) = matrix(z,y) - matrix(z,x) * factor
				Next
			EndIf
		Next
	Next
	
	For y=0 To size
		For z=0 To y-1
			matrix(size+1,size-y) = matrix(size+1,size-y) - matrix(size-z,size-y) * polynom(size-z)
		Next
		polynom(size-y) = matrix(size+1,size-y) / matrix(size-y,size-y)
	Next	
EndProcedure

Procedure CalcSpline(Array in.s_point(1))	
	Protected size.i = ArraySize(in())
	Protected Dim matrix.f(size*3,size*3-1)
	Protected Dim polynom.f(size*3-1)
	Protected x.i,y.i,z.i
	Protected value.f
	
	;/ create system of linear equations
	For z=0 To size-1
		matrix(z*3+0, 3*z+0)    = 1
		matrix(z*3+1, 3*z+0)    = in(z)\x
		matrix(z*3+2, 3*z+0)    = in(z)\x*in(z)\x
		matrix(size*3,3*z+0)   = in(z)\y
		matrix(z*3+0, 3*z+1)    = 1
		matrix(z*3+1, 3*z+1)    = in(z+1)\x
		matrix(z*3+2, 3*z+1)    = in(z+1)\x*in(z+1)\x
		matrix(size*3,3*z+1)   = in(z+1)\y
		If z <= size-2
			matrix(z*3+0, 3*z+2)    = 0
			matrix(z*3+1, 3*z+2)    = 1
			matrix(z*3+2, 3*z+2)    = 2*in(z+1)\x
			matrix(z*3+3, 3*z+2)    = 0
			matrix(z*3+4, 3*z+2)    = -1
			matrix(z*3+5, 3*z+2)    = -2*in(z+1)\x
		EndIf
	Next
	matrix(2,size*3-1) = 1
	
	;/ solve system
	solve(matrix(),polynom())
	
	;/ draw
	For z=0 To size-1
		For x=in(z)\x To in(z+1)\x
			
			value=0
			For y=0 To 2
				value + polynom(z*3+y) * Pow(x,y)
			Next
			If value >= 0 And value <= 600
				AddElement(p()) : p()\X = x : p()\Y = value
			EndIf			
		Next
	Next
	
	FirstElement(p())	
EndProcedure

Dim points.s_point(10)

points(0)\x = 50
points(0)\y = 480
points(1)\x = 100
points(1)\y = 140
points(2)\x = 150
points(2)\y = 80
points(3)\x = 200
points(3)\y = 120
points(4)\x = 250
points(4)\y = 90
points(5)\x = 300
points(5)\y = 140
points(6)\x = 350
points(6)\y = 100
points(7)\x = 400
points(7)\y = 320
points(8)\x = 450
points(8)\y = 440
points(9)\x = 500
points(9)\y = 480
points(10)\x = 550
points(10)\y = 420

CalcSpline(points())

CopyList(p(),tmp())

Define EventID, a
	
Repeat
	Repeat
		EventID = WindowEvent()
		If EventID = #PB_Event_CloseWindow : End : EndIf
	Until EventID = 0
	
	ClearScreen(0)
	
	StartDrawing(ScreenOutput())		
	For a=0 To 10
		Box(points(a)\x-1,points(a)\y-1,3,3,$0000FF)
	Next
	ForEach tmp()
		Plot(tmp()\x,tmp()\y)
	Next	
	StopDrawing()
	
	DisplayTransparentSprite(0,p()\X-64,p()\y-64)	
	NextElement(p())
	If ListIndex(p()) = ListSize(p()) - 1 : FirstElement(p()) : EndIf
		
	FlipBuffers()
ForEver
But is it possible to mix curved and straight points together? I mean that connection between two points is a straight line and not a curve.

Thanks for your great examples btw :o
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: Moving Sprite along predetermined path

Post by gnasen »

I think you're mixing up some things. The difference between a function and a curve is, that every value on the x-axis has not more then one value on the y-axis. Here a little pic:
Image
Curves are a little bit ugly, because they are equivalent to two functions (one for x/y axis).
However a curve is much more useful in programming, because a function would not allow to make loopings or something like that. Thats why the polynom and first spline interpolation havent been very good for a game.

I think you want, that the connection between the single points is some kind of more direct. Less of this loopings and arcs.
To reach this, it would need an interpolation of a higher degree.

The idea of a spline interpolation is pretty simple. Imagine you take 6 points, which you want to connect. Now you can take the first and the second point and connect them directly. This is a one degree interpolation and nothing you want.
So the next step would be an interpolation of degree 2, that means a function ax^2+bx+c between every pair of neighbouts. If you connect each pair of neighbours, you get 5 functions of 2nd degree. That makes 5*3=15 unknown variables.
First you know the start and end point of each pair (the points itself). If you substitute them into ax^2+bx+y (x,y are known!) you get 5*2 = 10 equations. So we need just 5 more to go.
We want, that they are connected smooth, so the derivative of the first functions end point has to be equal to the derivative of the second functions start point. We have 4 of this "crossing" points of functions, that makes 14 equations. Phew, nearly done!
For the last one we can use some trick. We just say: Hey, the first function should be linear, so a1=0. Ok, now we have our linear equation system complete. Solve, substitute, done.

The higher the degree of the interpolation, so more unknowns we get (an*x^n+....+a1*x+a0=y -> an,...,a0 unknowns). But as far as I see that should be no problem, because the calculations are done very fast.
The advantage is, that the functions can be much more accurate what means, that the points are more directly connected.
pb 5.11
Huitbit
User
User
Posts: 12
Joined: Thu Jun 11, 2009 4:56 am
Location: GUADELOUPE(F.W.I)

Re: Moving Sprite along predetermined path

Post by Huitbit »

Hi,

What about this ?
http://www.purebasic.fr/french/viewtopi ... ubdivision

And this ?
http://www.purebasic.fr/french/viewtopi ... on#p105574

It's very close to Bezier's curves but easier. All codes work fine with the pb4.51

It's in french :roll: ,but the final version (with fly and landing >>>>>under construction :| I'm time poor !) can be in the two languages !


Hasta la vista !
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: Moving Sprite along predetermined path

Post by gnasen »

Huitbit wrote:It's very close to Bezier's curves but easier
the problem is, that this is a very important fact. The subdivision or Bezier method (I think it was the first example from above) is a very good beginning, but it has the disadvantage, that not all points have to be crossed. If you order the points in a triangle, the middle point wont be hit with a blezier curve.
Maybe I missed something in your example, my french is really really bad ;)
pb 5.11
Huitbit
User
User
Posts: 12
Joined: Thu Jun 11, 2009 4:56 am
Location: GUADELOUPE(F.W.I)

Re: Moving Sprite along predetermined path

Post by Huitbit »

Hi,
my french is really really bad
I think it's good enough because I agree with you, gnasen :P .

But what kind of "paths" and "maths" needs exactly Fluid Byte ?

Subdivision doesn't need much CPU 's time. So, you can use it for many sprites at the same time, to change in realtime a curve, etc...
By using straight lines, you've got directly the slope...
You don't need a lot of "control points" to make a complex curve
To have more "control" on the curves, you can make a little "editor"
etc ,...


Hasta la vista !
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: Moving Sprite along predetermined path

Post by DarkDragon »

Hello,

I've just created a picture showing a possible solution (Maybe already shown by someone here, but its good for explanation):

Image
(Animated, wait a while if it doesn't show the animation)

If you want a curve to be between p1 and p2 with the modifier mp you can do it this way:
You've got a timefactor t = 0.0 to 1.0. For each t you have to get the interpolation-points
i1 = interpolation between p1 and mp
i2 = interpolation between mp and p2
Now you'll mix those 2 points this way:
At t = 0.0 the curve should hit the point p1 and as i1 = p1 you must weight i1 with factor 1.0 and i2 with 0.0
At t = 0.5 both interpolation points should be weighted the same, so weight i1 with 0.5 and i2 with 0.5
At t = 1.0 the curve should hit the point p2 and as i2 = p2 you must weight i1 with 0.0 and i2 with 1.0
The final formula for linear interpolation between those 2 points is
curvePoint = (1 - t) * i1 + t * i2

For hitting all of your points you could negate the directional vector to the next point after p2 and use it as mp.
bye,
Daniel
Post Reply