Need Acceleration Code for 3D Asteroid'sh Game

Blitz3D Forums/Blitz3D Programming/Need Acceleration Code for 3D Asteroid'sh Game

You can't use MoveEntity() like that. A fast-moving spaceship that turns around doesn't suddenly start travelling in the new direction it's facing. You need to model inertia for Asteroids-style physics.

Keep track of the velocity vector of your spaceship (vx, vy, and vz). When the ship accelerates, add a small amount to the velocity. To prevent the ship from going over a certain speed (Asteroids-style) normalize your velocity vector to your max speed if its magnitude is above the max speed. (This looks way simpler in code.)

I believe this example perfectly replicates the "physics" of the original Asteroids; specifically, how accellerating at a slight angle when already traveling at your max speed would affect your velocity. Controls: space accellerates, arrow keys turn on each axis of rotation.

Const TURN_SPEED# = 2
Const ACCEL# = .005
Const MAX_SPEED# = 1
Const GLOBAL_SPACE = 0
Const PLAYFIELD_SIZE# = 30

Graphics3D 800, 600

camera = CreateCamera()
PositionEntity(camera, 0, 0, -20)
light = CreateLight()

Type player
	Field entity
	Field x#, y#, z#
	Field vx#, vy#, vz#
End Type

Global p.player = New player
p\entity = CreateCone()

While Not(KeyHit(1))
	; input
	If KeyDown(200) Then TurnEntity(p\entity, TURN_SPEED, 0, 0)
	If KeyDown(208) Then TurnEntity(p\entity, -TURN_SPEED, 0, 0)
	If KeyDown(203) Then TurnEntity(p\entity, 0, 0, TURN_SPEED)
	If KeyDown(205) Then TurnEntity(p\entity, 0, 0, -TURN_SPEED)
	If KeyDown(57) Then
		; accellerate in the direction the player is facing (use Y axis because cones point in that direction)
		TFormVector 0, ACCEL, 0, p\entity, GLOBAL_SPACE
		p\vx = p\vx + TFormedX()
		p\vy = p\vy + TFormedY()
		p\vz = p\vz + TFormedZ()
		; measure current speed
		current_speed# = Sqr(p\vx*p\vx + p\vy*p\vy + p\vz*p\vz)
		If current_speed > MAX_SPEED Then
			; limit current speed to MAX_SPEED
			ratio_of_speed_to_keep# = MAX_SPEED / current_speed
			p\vx = p\vx * ratio_of_speed_to_keep
			p\vy = p\vy * ratio_of_speed_to_keep
			p\vz = p\vz * ratio_of_speed_to_keep
		EndIf
	EndIf
	
	; move the player
	p\x = p\x + p\vx
	p\y = p\y + p\vy
	p\z = p\z + p\vz
	
	; if the player goes off an edge of the playfield, move him to the other side
	While p\x < -PLAYFIELD_SIZE/2 : p\x = p\x + PLAYFIELD_SIZE : Wend
	While p\x >  PLAYFIELD_SIZE/2 : p\x = p\x - PLAYFIELD_SIZE : Wend
	While p\y < -PLAYFIELD_SIZE/2 : p\y = p\y + PLAYFIELD_SIZE : Wend
	While p\y >  PLAYFIELD_SIZE/2 : p\y = p\y - PLAYFIELD_SIZE : Wend
	While p\z < -PLAYFIELD_SIZE/2 : p\z = p\z + PLAYFIELD_SIZE : Wend
	While p\z >  PLAYFIELD_SIZE/2 : p\z = p\z - PLAYFIELD_SIZE : Wend
	
	; output
	PositionEntity(p\entity, p\x, p\y, p\z)
	RenderWorld
	Text 0, 0, "speed = " + current_speed
	Flip
Wend
End


That's the first time I've used the TForm* functions. Damn are they useful once you get the hang of them.