Dispite the look, it has nothing to do with the double pendulum. For exemple, "this" is use to move a robotic arms by its extremity.
Code: Select all
#x=600:#y=400
#nbBones=5
#lengthBone=50
#FixX=#X/2:#FixY=#Y/2
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or OpenWindow(0, 0, 0, #X, #Y, "Backward kinematic", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)=0 Or OpenWindowedScreen(WindowID(0),0,0,#X,#Y,0,0,0,#PB_Screen_WaitSynchronization)=0
MessageRequester("Error", "Can't open the sprite system", 0)
End
EndIf
Structure Bone
x1.i
y1.i
x2.i
y2.i
length.i
Angle.f
EndStructure
NewList Bone.Bone()
Procedure AddBone(List Bone.Bone(),length.i,angle.f)
If ListIndex(Bone())=-1
AddElement(Bone())
Bone()\x1=#FixX
Bone()\y1=#FixY
Else
xold.i=Bone()\x2
yold.i=Bone()\y2
AddElement(Bone())
Bone()\x1=xold
Bone()\y1=yold
EndIf
Bone()\Angle=angle:Bone()\length=length
Bone()\x2=Bone()\x1+Bone()\length*Cos(angle)
Bone()\y2=Bone()\y1+Bone()\length*Sin(angle)
EndProcedure
Procedure follow(List Bone.Bone(),targetX.i,targetY.i)
Bone()\Angle=ATan2(targetX-Bone()\x1,targetY-Bone()\y1)
Bone()\x2=Bone()\x1+Bone()\length*Cos(Bone()\Angle)
Bone()\y2=Bone()\y1+Bone()\length*Sin(Bone()\Angle)
a.i=Bone()\x2-Bone()\x1
b.i=Bone()\y2-Bone()\y1
Bone()\x2=targetx
Bone()\y2=targety
Bone()\x1=targetx-a
Bone()\y1=targety-b
EndProcedure
Procedure Update(List Bone.Bone(),xold.i,yold.i)
If LastElement(Bone())
Repeat
follow(Bone(),xold,yold)
xold=Bone()\x1
yold=Bone()\y1
Until PreviousElement(Bone())=0
;shift back to fix point
deltax.i=Bone()\x1-#FixX
deltay.i=Bone()\y1-#FixY
ForEach Bone()
Bone()\x1-deltax
Bone()\y1-deltay
Bone()\x2-deltax
Bone()\y2-deltay
Next
EndIf
EndProcedure
;create some bones...
For i=1 To #nbBones
AddBone(Bone(),#lengthBone,Radian(-90))
Next i
Dx.i=2:Dy.i=2:x.i=Random(#X):y.i=Random(#Y)
Repeat
FlipBuffers()
ClearScreen(RGB(0,0,0))
ExamineKeyboard()
;bouncing box
If x>#x Or x<0:Dx=-Dx:EndIf
If y>#y Or y<0:Dy=-Dy:EndIf
x+Dx:y+Dy
Update(Bone(),x,y)
StartDrawing(ScreenOutput())
Circle(x,y,10,#Red)
ForEach Bone()
LineXY(Bone()\x1,Bone()\y1,Bone()\x2,Bone()\y2,#Blue)
Circle(Bone()\x2,Bone()\y2,2,#White)
Next
Circle(#FixX,#FixY,3,#Green)
StopDrawing()
Repeat:Event = WindowEvent():If event= #PB_Event_CloseWindow:End:EndIf:Until event=0
Until KeyboardPushed(#PB_Key_Escape)