"Snake" segment logic

Blitz3D Forums/Blitz3D Programming/"Snake" segment logic

_PJ_(Posted 2016) [#1]
I am unable to ascertain why the segments are not moving in the intended directon.




Function MoveSegment(S.SEGMENT)
	;Calculate position relative to target position
	Local X#=EntityX#(S\Entity,True)
	Local TX#=(S\TargetPos[0]-X#)
	Local Z#=EntityZ#(S\Entity,True)
	Local TZ#=(S\TargetPos[1]-Z#)
	
	;Only set a new target position when close enough to the target position
	If ((Sqr(TX*TX)+(TZ*TZ))<0.2)
		If (S\Segment=0)
;This is the first segment, so set target as the position of the HEAD
			S\TargetPos[0]=EntityX#(S\Parent\Entity,True)
			S\TargetPos[1]=EntityZ#(S\Parent\Entity,True)
		Else
;Use the preceeding Segment location as Target
			Local P.SEGMENT
			P=Object.SEGMENT(S\Parent\Segment[S\Segment-1])
			S\TargetPos[0]=EntityX#(P\Entity,True)
			S\TargetPos[1]=EntityZ#(P\Entity,True)
		End If
	End If
	
	;Use TX and TZ to represent target coords for simplicity
	TX#=S\TargetPos[0]
	TZ#=S\TargetPos[1]
	
	;Fix for wraparound
	If (Abs(TX-X)>2.0)
		If X>TX Then TX=MAPSIZEX+1
		If X<TX Then TX=-1
	End If
	
	;Ensure pointing towards target and move forwards
	Local Yaw#=Angle2D(X,Z,TX,TZ)
	RotateEntity S\Entity,0,Yaw#,0,True
	MoveEntity S\Entity,0,0,0.1
	
	DebugLog(S\Segment+": "+LSet(Yaw,5)+" "+LSet(X,5)+","+LSet(Z,5)+" "+LSet(S\TargetPos[0],5)+","+LSet(S\TargetPos[1],5))
	
End Function


Initially, Each segment YAW value is set to match the YAW of the HEAD Segement SEGMENT\Parent\Entity


Bear in mind this is NOT identical to the 'snake' game, so there is no consideration for extending the number of segments or concerns over segment collisions etc.


_PJ_(Posted 2016) [#2]
I should include this:
Function Angle2D#( x1#,y1#,x2#,y2# )
	Return 180-ATan2(x2-x1,y2-y1)
End Function



_PJ_(Posted 2016) [#3]
Nevermind. All solved.

Function MoveSegment(S.SEGMENT)
	;Calculate position relative to target position
	Local X#=EntityX#(S\Entity,True)
	Local TX#=(S\TargetPos[0]-X#)
	Local Z#=EntityZ#(S\Entity,True)
	Local TZ#=(S\TargetPos[1]-Z#)
	
	;Only set a new target position when close enough to the target position
	If ((Sqr(TX*TX)+(TZ*TZ))<0.2)
		If (S\Segment=1)
			;This is first segment, use Head position as target
			S\TargetPos[0]=EntityX#(S\Parent\Entity,True)
			S\TargetPos[1]=EntityZ#(S\Parent\Entity,True)
		Else
			;Use preceeding segment position as target
			Local P.SEGMENT
			P=Object.SEGMENT(S\Parent\Segment[S\Segment-2])
			S\TargetPos[0]=EntityX#(P\Entity,True)
			S\TargetPos[1]=EntityZ#(P\Entity,True)
		End If
	End If
	
	;Use TX and TZ to represent target coords for simplicity
	TX#=S\TargetPos[0]
	TZ#=S\TargetPos[1]
	
	;Fix for wraparound
	If (Abs(TX-X)>2.0)
		If X>TX Then TX=MAPSIZEX+1
		If X<TX Then TX=-1
	End If
	
	;Ensure pointing towards target and move forwards
	Local Yaw#=Angle2D(TX,TZ,X,Z)
	RotateEntity S\Entity,0,Yaw#,0,True
	MoveEntity S\Entity,0,0,0.1
	
	DebugLog(S\Segment+": "+LSet(Yaw,5)+" "+LSet(X,5)+","+LSet(Z,5)+" "+LSet(S\TargetPos[0],5)+","+LSet(S\TargetPos[1],5))
	
End Function	

Function Angle2D#( x1#,y1#,x2#,y2# )
	Return 360.0- (ATan2(x1-x2,y1-y2))
End Function