space ship movement simulate roll

BlitzMax Forums/BlitzMax Programming/space ship movement simulate roll

hub(Posted 2009) [#1]
Hi !
i'm searching a method to simulate a ship roll with an imagestrip image (see my picture).
Some ideas or formulae to do this ?

note : i've already the code to move the ship along the spline and orient the image to the direction. But i don't know how to determine and simulate the roll.

Thanks for your help !


Pete Rigz(Posted 2009) [#2]
I would measure the difference in degrees that it changed direction since the last frame and tie that in with the animation frame. So you just have to think about how many degrees represents which frame, so if it turned 1-10 degrees it should show frame 1, 11-20 frame 2 etc.

something like

frame=int(change_in_degrees/40*number_of_turning_frames)
if frame> number_of_turning_frames frame=number_of_turning_frames

40 is just a number plucked out of the air but it should be the maximum number of degrees that represents the last frame of the turning animation. Something along those lines anyway.


lukehedman(Posted 2009) [#3]
There's (almost) nothing in deep space. With no atmosphere there's no need for a ship to roll. Of course, there's no sound either, but my project still has lasers that scream like demons from hell. :-D

Pete's suggestion sounds solid. Just calculate the difference between the object's heading at the current and last update. This code should make it easy.


Function FAngleDifference:Double(ActorA:TActor, ActorB:TActor)
		
	Local AngleLessAngle:Double = ActorB.Angle - ActorA.Angle
		
	If AngleLessAngle > 180
		
		Return(AngleLessAngle - 360)
		
	End If
		
	If AngleLessAngle < - 180
		
		Return(AngleLessAngle + 360)
		
	End If
		
	Return(AngleLessAngle)
	
End Function



I hope that helps. Good luck with your game.


hub(Posted 2009) [#4]
Thanks for your help. Could you help me again. I've written this piece of code (spline code is not mine) ... not work at this time because i don't know how to use the computed roll value. So i need some help to write the Display_ship function ! Note that it should work with any spline !

Graphics 1024,768,0

Global himage = LoadAnimImage ("imagestrip_ennemi1.png",106,80,0,13)
If himage = Null Notify "load image bug !"
MidHandleImage hImage

'--------------
' functions
'-------------

Function bezier(ax#,ay#,bx#,by#,cx#,cy#,dx#,dy#)
	SetColor 255,0,0
	DrawLine ax,ay,bx,by
	DrawLine cx,cy,dx,dy
	ox#=ax
	oy#=ay
	SetColor 100,100,100
	For t#=0 To 1 Step .01
		a#=t
		b#=1-t
		x#=ax*b*b*b + 3*bx*b*b*a + 3*cx*b*a*a + dx*a*a*a
		y#=ay*b*b*b + 3*by*b*b*a + 3*cy*b*a*a + dy*a*a*a
		DrawRect x-1,y-1,3,3
		DrawLine ox,oy,x,y
		ox=x
		oy=y
	Next
End Function

Function Display_ship (x#,y#,roll#)

		If Roll <= -0.6 Then f = 0
		If Roll <= -0.5 And Roll > -0.6 Then f = 1
		If Roll <= -0.4 And Roll > -0.5 Then f = 2
		If Roll <= -0.3 And Roll > -0.4 Then f = 3
		If Roll <= -0.2 And Roll > -0.3 Then f = 4
		If Roll <= -0.1 And Roll > -0.2 Then f = 5

		If Roll = 0.0 Then f = 6

		If Roll >= 0.1 And Roll < 0.2 Then f = 7
		If Roll >= 0.2 And Roll < 0.3 Then f = 8
		If Roll >= 0.3 And Roll < 0.4 Then f = 9
		If Roll >= 0.4 And Roll < 0.5 Then f = 10
		If Roll >= 0.5 And Roll < 0.6 Then f = 11
		If Roll >= 0.6 Then f = 12
	
		DrawImage hImage, x#,y#, f
	
End Function

'--------------
' main program
'-------------

' spline points and control points here :
' **************************************************************
Local ax=200, ay=50, bx=600, by=40, cx=300, cy=700, dx=800, dy=588
' **************************************************************


t1#=0
t2#=0
speed#=0 
x1#=ax
y1#=ay
x2#=ax
y2#=ay

SetClsColor 255,255,255

While Not KeyHit(KEY_ESCAPE)

	' display the spline
	
	bezier(ax,ay,bx,by,cx,cy,dx,dy) 
	
	'compute classic spline movement.
	
	ox1#=x1
	oy1#=y1
	ox2#=x2
	oy2#=y2
	
	t1:+speed
	If t1>1 Then t1=0
	a#=t1
	b#=1-t1

	old_x1# = x1#
	old_y1# = y1#
	old_rot1# = rot1#
	x1#=ax*b^3 + 3*bx*b^2*a + 3*cx*b*a^2 + dx * a^3
	y1#=ay*b^3 + 3*by*b^2*a + 3*cy*b*a^2 + dy * a^3
	rot1 = 360 - ATan2 (x1# - old_x1#, y1# - old_y1#)

	'determine roll1
	'**************************** 
	roll1# = old_rot1# - rot1
	'**************************** 

	'compute equidistant point spline movement.

	SetRotation rot1
	Display_ship (x1-3,y1-3, roll1#)
	SetRotation 0
	SetColor 255,0,0
	DrawRect x1-3,y1-3,7,7
	DrawText "roll1=" + roll1#,x1,y1
	SetColor 255,255,255

	vx#=-3*ax*b*b + 3*bx*b*(b-2*a) + 3*cx*a*(2*b-a) + dx*3*a*a
	vy#=-3*ay*b*b + 3*by*b*(b-2*a) + 3*cy*a*(2*b-a) + dy*3*a*a
	d#=Sqr(vx*vx+vy*vy)

	speed#=10/d 

	t2:+.001
	If t2>1 Then t2=0
	a#=t2
	b#=1-t2
	old_x2# = x2#
	old_y2# = y2#
	old_rot2# = rot2#
	x2#=ax*b*b*b + 3*bx*b*b*a + 3*cx*b*a*a + dx*a*a*a
	y2#=ay*b*b*b + 3*by*b*b*a + 3*cy*b*a*a + dy*a*a*a
	rot2 = 360 - ATan2 (x2# - old_x2#, y2# - old_y2#)

	' determine roll2
	'**************************** 
	roll2# = old_rot2# - rot2
	'****************************
	
	SetRotation rot2
	Display_ship (x2-3,y2-3, roll2#)
	SetRotation 0
	SetColor 0,0,255
	DrawRect x2-3,y2-3,7,7
	DrawText "roll2=" + roll2#, x2,y2
	SetColor 255,255,255

	Delay 30

	Flip
	Cls
Wend



Download the ship graphics file here :
Download the ship graphics file here :



Pete Rigz(Posted 2009) [#5]
maybe something like this:

Function Display_ship (x:Float, y:Float, roll:Float, rollfactor:Float = 4)

	Local f:Int = 6
	        
	If roll < - 0.1
		f = Abs(roll) / rollfactor * 6 + 7
		If f > 12 f = 12
	ElseIf roll > 0.1
		f = Abs(6 - (roll / rollfactor * 6))
		If f > 5 f = 5
	End If
	        
	DrawImage hImage, x, y, f
       
End Function


Rollfactor determines the number of degrees that represents the last frame of roll animation.


hub(Posted 2009) [#6]
this works fine now, many thanks Pete for the function. Here a final code. You can drag the spline points to test...

Download the ship graphics file here.


Graphics 1024,768,0

Global himage = LoadAnimImage ("imagestrip_ennemi1.png",106,80,0,13)
If himage = Null Notify "load image bug !"
MidHandleImage hImage

'--------------
' functions
'-------------

Function bezier(ax#,ay#,bx#,by#,cx#,cy#,dx#,dy#)
	SetColor 255,0,0
	DrawLine ax,ay,bx,by
	DrawLine cx,cy,dx,dy
	ox#=ax
	oy#=ay
	SetColor 100,100,100
	For t#=0 To 1 Step .01
		a#=t
		b#=1-t
		x#=ax*b*b*b + 3*bx*b*b*a + 3*cx*b*a*a + dx*a*a*a
		y#=ay*b*b*b + 3*by*b*b*a + 3*cy*b*a*a + dy*a*a*a
		DrawRect x-1,y-1,3,3
		DrawLine ox,oy,x,y
		ox=x
		oy=y
	Next
End Function

Function Display_ship (x:Float, y:Float, roll:Float, rollfactor:Float = 4)

	' Rollfactor determines the number of degrees that represents the last frame of roll animation.

	Local f:Int = 6
	        
	If roll < - 0.1
		f = Abs(roll) / rollfactor * 6 + 7
		If f > 12 f = 12
	ElseIf roll > 0.1
		f = Abs(6 - (roll / rollfactor * 6))
		If f > 5 f = 5
	End If
	        
	DrawImage hImage, x, y, f
       
End Function

Function Drag_points ()

	mx = MouseX()
	my = MouseY()
	
	If MouseDown (1) Or MouseDown(2) Then
	
		If mx - 30 < ax And mx + 30 > ax Then
			If my - 30 < ay And my + 30 > ay Then
				ax = mx
				ay = my
			End If
		End If
		
		If mx - 30 < bx And mx + 30 > bx Then
			If my - 30 < by And my + 30 > by Then
				bx = mx
				by = my
			End If
		End If
	
		If mx - 30 < cx And mx + 30 > cx Then
			If my - 30 < cy And my + 30 > cy Then
				cx = mx
				cy = my
			End If
		End If
	
		If mx - 30 < dx And mx + 30 > dx Then
			If my - 30 < dy And my + 30 > dy Then
				dx = mx
				dy = my
			End If
		End If
	End If
	
	SetColor 255,0,0
	DrawOval mx-3,my-3,6,6
	DrawText (mx + "," + my), mx,my + 16
	SetColor 255,255,255


End Function

'--------------
' main program
'-------------

' spline points and control points here :
' **************************************************************
Global  ax=200, ay=50, bx=600, by=40, cx=300, cy=700, dx=800, dy=588
' **************************************************************


t1#=0
t2#=0
speed#=0 
x1#=ax
y1#=ay
x2#=ax
y2#=ay

HideMouse 

SetClsColor 255,255,255

While Not KeyHit(KEY_ESCAPE)

	' dragpoints
	
	Drag_points ()
	
	' display the spline
	
	bezier(ax,ay,bx,by,cx,cy,dx,dy) 
	
	'compute classic spline movement.
	
	ox1#=x1
	oy1#=y1
	ox2#=x2
	oy2#=y2
	
	t1:+speed
	
	If t1>1 Then 
		t1=0
		f1 = 6
		f2 = 6
	End If
	
	a#=t1
	b#=1-t1

	old_x1# = x1#
	old_y1# = y1#
	old_rot1# = rot1#
	x1#=ax*b^3 + 3*bx*b^2*a + 3*cx*b*a^2 + dx * a^3
	y1#=ay*b^3 + 3*by*b^2*a + 3*cy*b*a^2 + dy * a^3
	rot1 = 360 - ATan2 (x1# - old_x1#, y1# - old_y1#)

	'determine roll1
	'**************************** 
	roll1# = old_rot1# - rot1
	'**************************** 

	'compute equidistant point spline movement.

	SetRotation rot1
	Display_ship (x1-3,y1-3, roll1#)
	SetRotation 0
	SetColor 255,0,0
	DrawRect x1-3,y1-3,7,7
	DrawText "roll1 = " + roll1# ,x1,y1
	SetColor 255,255,255

	vx#=-3*ax*b*b + 3*bx*b*(b-2*a) + 3*cx*a*(2*b-a) + dx*3*a*a
	vy#=-3*ay*b*b + 3*by*b*(b-2*a) + 3*cy*a*(2*b-a) + dy*3*a*a
	d#=Sqr(vx*vx+vy*vy)

	speed#=10/d 

	t2:+.001
	If t2>1 Then t2=0
	a#=t2
	b#=1-t2
	old_x2# = x2#
	old_y2# = y2#
	old_rot2# = rot2#
	x2#=ax*b*b*b + 3*bx*b*b*a + 3*cx*b*a*a + dx*a*a*a
	y2#=ay*b*b*b + 3*by*b*b*a + 3*cy*b*a*a + dy*a*a*a
	rot2 = 360 - ATan2 (x2# - old_x2#, y2# - old_y2#)

	' determine roll2
	'**************************** 
	roll2# = old_rot2# - rot2
	'****************************
	
	SetRotation rot2
	Display_ship (x2-3,y2-3, roll2#)
	SetRotation 0
	SetColor 0,0,255
	DrawRect x2-3,y2-3,7,7
	DrawText "roll2=" + roll2#, x2,y2
	SetColor 255,255,255
	
	Flip

	Cls
Wend

ShowMouse





hub(Posted 2010) [#7]
finaly after read again my code i've some problem to understand this :

"Rollfactor determines the number of degrees that represents the last frame of roll animation."

Could you explain me ?

Thanks

(now i've 16 frames imagestrip)
(frame 0 : -30 degrees, frame 8 : 0 degree, frame 15 : 30 degrees)



hub(Posted 2010) [#8]
i just need some help to determine the rollfactor value with this imagestrip.
Thanks.


Pete Rigz(Posted 2010) [#9]
The value of roll that you pass to the function is the number of degrees that the ship is turning. The more degrees that the ship turns the more the ship tilts. So the rollfactor is the maximum number of degrees that represents the last frame number with the steepest roll. It looks like the main problem is that the animation you're using has more frames then the original, the function I wrote was hard coded for 12 frames of animation. Maybe this is more flexible:

Function Display_ship (x:Float, y:Float, roll:Float, frames:int ,rollfactor:Float = 4)

	' Rollfactor determines the number of degrees that represents the last frame of roll animation.

        Local middleframe:int=frames/2
	Local f:Int = middleframe
	        
	If roll < - 0.1
		f = Abs(roll) / rollfactor * middleframe + middleframe+1
		If f > frames-1 f = frames-1
	ElseIf roll > 0.1
		f = Abs(middleframe - (roll / rollfactor * middleframe))
		If f > middleframe-1 f = middleframe-1
	End If
	        
	DrawImage hImage, x, y, f
       
End Function


Also the image strip you have there is 16 frames which means there is no middle frame. I think the previous strip you had was 13 frames, so frame 7 was the middle frame and you had 6 frames either side. The above code might need tweaking as I haven't tested it at all, but might not work properly unless you have an odd number of frames, like 17 for instance.