space ship inertia

BlitzMax Forums/BlitzMax Beginners Area/space ship inertia

how do I add friction or inertia type movement to the space ship object?

where the ship continues heading in the last direction you were thrusting in, even if your rotation has changed. and also to be heading in that direction at the same speed you stopped thrusting at, i.e no slowing down as time goes by, so i guess thats newtonian and not just friction, friction would slow you down after a while.

so

vx :+ Sin(angle)*speed
vy :+ Cos(angle)*speed

x  :+  vx
y  :-  vy



that gives the proper direction and stuff, but what to carry on the speed no matter the angle?

currently of course as soon as you change angle, it starts going in that directrion.

The key is to only update your vx and vy while you are applying the thruster.

Otherwise, just leave vx and vy alone (unless you do want to add in some sort of friction).

Oh, and get rid of that *speed. I'm pretty sure (w/o having tested it) that that is what is causing your problem. Vx and Vy represent your speed.


So now we'll let vx and vy represent your speed, and set the necessary caps on them. I'd personally keep vx and vy between 0 and 1.0 and then multiply them by a constant representing your MAXSPEED later.

Of course, you'll need to multiply your Sin(angle) by some constant value as well, to keep the values small so that vx and vy don't climb from 0.0 to 1.0 too fast.

Here's some quick and dirty code (not tested). Space bar represents the thruster here. Adjust the const's to taste - I have no idea if the values I put in actually work decently or not ;).
const THRUST_MULTIPLIER:float = 0.005
const MAX_HORIZONTAL_VELOCITY = 10
const MAX_VERTICAL_VELOCITY = 10

if Keydown( key_space )

vx:+ sin(angle) *  THRUST_MULTIPLIER
vy:+ cos(angle) * THRUST_MULTIPLIER

if vx > 1.0
 vx = 1.0
endif

if vx < -1.0
 vx = -1.0
endif

if vy > 1.0
 vy = 1.0
endif

if vy < -1.0
 vy = -1.0
endif


endif

x:+ (vx * MAX_HORIZONTAL_VELOCITY)
y:+ (vy * MAX_VERTICAL_VELOCITY)



Asteroids is the classic example of this type of movement - take a look at this tutorial:

http://www.blitzbasic.com/Community/posts.php?topic=48800

Had this to hand if it helps any...
Strict

Type TPoint2D
	Field x#, y#
End Type

Type TVectObj
	Field originX#, originY#
	Field scaleX# = 1, scaleY# = 1
	Field rotation#, alpha# = 1
	Field r, g, b
	
	Field points:TPoint2D[]
	
	Method AddPoint(x#, y#)
		Local thisPoint:TPoint2D = New TPoint2D
		thisPoint.x# = x#
		thisPoint.y# = y#
		
		points = points[..points.length + 1]
		points[points.length - 1] = thisPoint
	End Method
	
	Method SetColour(r, g, b)
		Self.r = r
		Self.g = g
		Self.b = b
	End Method
	
	Method SetScale(x#, y#)
		scaleX# = x#
		scaleY# = y#
	End Method
	
	Method Draw()
		SetTransform rotation#, scaleX#, scaleY#
		SetColor r, g, b
		
		For Local thisPoint = 0 Until points.length
			Local nextPoint = (thisPoint + 1) Mod points.length
			Local handleX# = originX# - (originX# + points[thisPoint].x#)
			Local handleY# = originY# - (originY# + points[thisPoint].y#)
			
			SetHandle handleX#, handleY#
			DrawLine originX# ,originY#,..
							(originX# + Points[nextPoint].x#) + handleX#,..
							(originY# + Points[nextPoint].y#) + handleY#
		Next
	End Method
End Type

Type TPlayer
	Field ship:TVectObj
	Field vx#, vy#
	
	Function Create:TPlayer(ship:TVectObj, x#, y#)
		Local thisPlayer:TPlayer = New TPlayer
		
		thisPlayer.ship = ship
		thisPlayer.ship.originX# = x#
		thisPlayer.ship.originY# = y#
		
		Return thisPlayer
	End Function
	
	Method Update()	
		Local thrustX#, thrustY#
		
		If KeyDown(KEY_LEFT)
			ship.rotation# :- 4
		EndIf
		
		If KeyDown(KEY_RIGHT)
			ship.rotation# :+ 4
		EndIf
		
		If KeyDown(KEY_UP)
			vx# :+ Sin(ship.rotation#) * 0.1
		 	vy# :- Cos(ship.rotation#) * 0.1
		Else
			vx# :* 0.99
			vy# :* 0.99
		EndIf
		
		ship.originX# :+ vx#
		ship.originY# :+ vy#
		
		If ship.originX# < 0
			ship.originX# = GraphicsWidth()
		Else
			If ship.originX# > GraphicsWidth() Then ship.originX# = 0
		EndIf
		
		If ship.originY# < 0
			ship.originY# = GraphicsHeight()
		Else
			If ship.originY# > GraphicsHeight() Then ship.originY# = 0
		EndIf	
	End Method
	
	Method Draw()
		ship.Draw()
	End Method	
End Type		
		
	
SetGraphicsDriver GLMax2DDriver()
Graphics 800, 600, 32'0
HideMouse

Local ship:TVectObj = New TVectObj
ship.AddPoint(0, -10)
ship.AddPoint(10, 10)
ship.AddPoint(0, 7.5)
ship.AddPoint(-10, 10)
ship.SetColour(200, 255, 255)

Local player:TPlayer = TPlayer.Create(ship, 400, 300)

glEnable(GL_LINE_SMOOTH)
SetLineWidth 2'0.25

Repeat
	Clear()
	
	'ship.SetScale(1 + (Cos(MilliSecs() * 1.5) * 0.1), 1 + (Sin(MilliSecs() * 1.5) * 0.1))	
	player.Update()
	
	SetAlpha 0.5
	player.Draw()
	
	'FlushMem
	
	Flip
Until KeyHit(KEY_ESCAPE)

End

Function Clear(alpha#=0.6) 
	SetColor 0, 0, 0
	SetHandle 0, 0
	SetTransform 0, 1, 1
	SetBlend ALPHABLEND
	SetAlpha alpha#
	DrawRect 0, 0, 800, 600
End Function


[edit]
Ha...Probably not then. ;o)
[/edit]

thanks guys. got it, i just had to put the vector code in the thrust input. where as before it was in an update physics method in the loop, now I put the cos sin of vx vy in the forward thrust and rear thrust and leave the x+vx stuff in the update physics method and it works, after testing for a few seconds, so who knows if i run into something else along the way. I want this type of movement for a different game than the one i am doing now.

@Sculpture - I like your way, but I found a nice way of keeping it below max speed, but you cant use your 0.0 to 1.0 idea. Here is the code for a Thrust() method:
Const MAX_SPEED:Float = 6.0
Const ACCELERATION:Float = 0.1

'# vx = x part of velocity
'# vy = y part of velocity
'# dir = direction facing

'# change vx and vy depending on what direction the ship is facing
vx :+ ACCELERATION * Cos(dir)
vy :+ ACCELERATION * Sin(dir)

'# this keeps the overall speed below max speed no matter what
If Sqr(vx * vx + vy * vy) > MAX_SPEED
    Local a:Float = ATan2(vy, vx)
    vx = MAX_SPEED * Cos(a)
    vy = MAX_SPEED * Sin(a)
EndIf


Hmm, I see what you're doing (i think). If the length of the velocity vector is > max speed you calculate the angle the ship is traveling at, and then set vx and vy according to that, thus preventing the player from ever actually exceeding MAX_SPEED in any direction (where my code would let you travel at MAX_SPEED if you were heading strictly horizontally or vertically, but greater than MAX_SPEED when moving diagonally).

Nice!

One of these days I might actually get around to working with physics/graphics with real code (I built an inertia engine in Click & Create, hehe, but other than C&C games I've never really programmed physics/graphics). Until then, I apologize for half-baked ideas off the top of my head ;).

Yeah, the first time I tried this I just checked if vx and vy were greater than MAX_SPEED but then yeah you could go greater than MAX_SPEED by going diagonally. I spent a long time trying to figure out how to fix that, and I finally found out about ATan and ATan2 and now it works great.

oops, double post.

You could also lose the trig...
local VelMag = Sqr((vx * vx) + (vy * vy)) 
If VelMag > MAX_SPEED
    vx = (vx / VelMag) * MAX_SPEED
    vy = (vy / VelMag) * MAX_SPEED
EndIf