Timing movements in seconds?

Blitz3D Forums/Blitz3D Beginners Area/Timing movements in seconds?

Hi,

I need a timing system that uses seconds and not animation frames to govern the movements of objects in a scene.

The CreateTimer(), WaitTimer() approach is no good in this instance because it uses frame frequency.

Can someone who knows basic mathematics show me why the following code doesn't work.

; Basic timed movement
; ------------------
;
; doesn't work. Why?
;
; need to move the object over a set distance (6.5) in a set time (3 secs) 
; time needs to be in seconds NOT frames


; Set 3D graphics mode
Graphics3D 640,480,16,0
SetBuffer BackBuffer()

camera=CreateCamera()
light=CreateLight()

cone=CreateCone( 32 )
PositionEntity cone,-3,0,5

distance#   = 6.5 ;blitz units
time#       = 3.0 ;secs
speed#      = Float(distance / time)

currentpos# = 0.0 

While Not KeyDown( 1 )
		
	If (currentpos < distance)
	
		MoveEntity(cone, speed, 0, 0)
		currentpos = currentpos + speed
		
	EndIf

	UpdateWorld()
	RenderWorld()
	
	Flip

Wend

ClearWorld()

End



Thanks,

Rogue Vector

Greetings Puppies,

Check out the Millisecs() command and base your stuff on that?

Peace,

Jes

I know about the millisecs() command.

But there are still problems with the timing.

Objects move in a jerky way and inaccuracy creeps in.

Observe,
; Basic timed movement
; ------------------
; 
; need to move the object over a set distance (6.5) in a set time (3 secs) 
; time needs to be in seconds NOT frames
;
; PROBLEM - NOT ACCURATE and the object needs to move more smoothly and eliminated the jerkyness 
;-----------------------------------------------------------------------------

; Set 3D graphics mode
Graphics3D 640,480,16,0
SetBuffer BackBuffer()

camera=CreateCamera()
light=CreateLight()

cone=CreateCone( 32 )
PositionEntity cone,-3,0,5

distance#   = 6.5 ;blitz units
time#       = 3.0 ;seconds
speed#      = Float(distance / time);result is blitz units per second

currentpos# = 0.0 

clock = 0
timer = 0

While Not KeyDown( 1 )

	clock = MilliSecs()

	If (timer + Float(1000 / 4)  < clock) ;clock every 250 milliseconds (1/4 second)
		
		If (currentpos < distance)
		
			MoveEntity(cone, speed / 4 , 0, 0)
			currentpos = currentpos + speed / 4
				
		EndIf

		timer = clock
		
	EndIf	

	UpdateWorld()
	RenderWorld()
		
	Text 2, 5, CurrentTime$()
	
	Flip
	
Wend

ClearWorld()

End


Rogue Vector

Instead of moving the object every 250 milliseconds, you need to move the object based on the number of miilisecs since the last update. Like this:

; Set 3D graphics mode
Graphics3D 640,480,16,0
SetBuffer BackBuffer()

camera=CreateCamera()
light=CreateLight()

cone=CreateCone( 32 )
PositionEntity cone,-3,0,5

distance#     = 6.5 ;blitz units
time#         = 3.0 ;seconds
speed#        = Float(distance / time);result is blitz units per second
speedpertick# = Float(speed#/1000);result is blitz units per tick

currentpos# = 0.0 

clock = MilliSecs()
starttime = clock


While Not KeyDown( 1 )
	
	ticks = MilliSecs() - clock
	clock = MilliSecs()

	If (currentpos < distance)
		distancemovedthisupdate# = speedpertick# * ticks
		MoveEntity(cone, distancemovedthisupdate, 0, 0)
		currentpos = currentpos + distancemovedthisupdate
	Else
		Text 2, 60, "Took " + (MilliSecs() - StartTime) + " milliseconds"
		Flip
		WaitKey
		End
	End If
		
	UpdateWorld()
	RenderWorld()
		
	Text 2, 5, CurrentTime$()
	Text 2, 30, currentpos

	Flip
	
Wend

ClearWorld()

End


That way it always moves at the same speed regardless of the framerate.

Edit: sorry, I didn't notice the significance of currentpos at first :-)

Edit: also, it'll never be *exactly* 6.5 units, or 3000 milliseconds because of the vagaries of PC performance, (my PC was doing a frame about every 17 milliseconds, which just doesn't divide cleanly into 3000) but it should be accurate enough for most purposes.

Thanks!

Rogue Vector,

No problem.

Rogue Vector, take a look at my Frame Limiting Code (the link is on the left) to see how to apply it to your games.
http://home.cmit.net/rwolbeck/programmingtutorial