Game Timing

BlitzMax Forums/BlitzMax Programming/Game Timing

Sean Doherty(Posted 2005) [#1]
The following article talks about time steping:

http://www.gaffer.org/articles/Timestep.html

Also, I noticed that many people prefer delta time. However, I lot of people reference code by mark that I can't seem to find? Anyone have the link to this post?

Also, for Delta Time do you multiple everything by the Delta Time or just the final result?


Leiden(Posted 2005) [#2]
For Delta timing you multiply all movement my the delta time, that way it can pump out Max FPS but the movement (and logic?) will only tick along at the delta time. Say:

B3D Example:
MoveEntity Player, 0, 0, 10 * DeltaTime


I think alot of the reference to Mark's timing is actually from the Mak Castle Demo in the Blitz3D Samples Folder.

Timing code:
Const FPS=30
period=1000/FPS
time=MilliSecs()-period

While not keydown(001) ; Main Loop

Repeat
		elapsed=MilliSecs()-time
	Until elapsed

	;how many 'frames' have elapsed	
	ticks=elapsed/period
	
	;fractional remainder
	tween#=Float(elapsed Mod period)/Float(period)
	
	For k=1 To ticks
		time=time+period
		If k=ticks Then CaptureWorld
		
		UpdateGame()
		UpdateWorld
	Next
Renderworld tween#


Its pretty easy to follow. Hope it helps :)


Grey Alien(Posted 2005) [#3]
That deltatime example wastes a millisecond per frame, does it crash if elapsed = 0?


Leiden(Posted 2005) [#4]
Thats not deltatiming thats the rendertween code from the castle demo. But looking at it now I would guess it would end up giving a divide by zero error. I didnt bother to run it as I dont have my B3D copy at hand.


Grey Alien(Posted 2005) [#5]
oh OK, actually elapsed isn't used on the end of a divide statement so it wouldn't divide by zero. It's alright on the start of a divide statement as 0/10 = 0 for example.


Leiden(Posted 2005) [#6]
Ahh I see, my mistake. One day I'll actually nuckle down and try to understand mathematical concepts :S


Tibit(Posted 2005) [#7]
This might help:



I hope the comments are still valid. I like having a Delta Type, it really makes it cleaner.


Sean Doherty(Posted 2005) [#8]
Where do I apply the Delta Time multiplier:


'Calculate the length of the Speed Vector
		Local SpeedVectorLength# = sqr(m_fSpeedX*m_fSpeedX + m_fSpeedY*m_fSpeedY)
		
		If SpeedVectorLength > 0
			'Decrease Speed with Friction if we are moving
			m_fSpeedX:- (m_fSpeedX/SpeedVectorLength) * m_pTEngine.GetFriction() * TDelta.GetTime()
			m_fSpeedY:- (m_fSpeedY/SpeedVectorLength) * m_pTEngine.GetFriction() * TDelta.GetTime()
		Else
			m_fSpeedX=0
			m_fSpeedY=0
		EndIf
		
		Print TDelta.GetTime()
		
		If SpeedVectorLength > m_pTEngine.GetMaximumVelocity()
			'If we are going beyond the speed barrier then reduce our speed
			'with the amount in which it surpases TopSpeed
			m_fSpeedX:+ (m_fSpeedX/SpeedVectorLength)*(m_pTEngine.GetMaximumVelocity() - SpeedVectorLength) * TDelta.GetTime()
			m_fSpeedY:+ (m_fSpeedY/SpeedVectorLength)*(m_pTEngine.GetMaximumVelocity() - SpeedVectorLength) * TDelta.GetTime()
		EndIf
		
		If SpeedVectorLength > 0  
			m_fX:+ m_fSpeedX 
			m_fY:+ m_fSpeedY
		End If


	Method IncreaseVelocity()
		'Create a Acceleration Vector and
		'add it to the Speed Vector
		m_fSpeedX:+ Cos(m_fAngle) * m_pTEngine.GetAcceleration() * TDelta.GetTime()
		m_fSpeedY:+ Sin(m_fAngle) * m_pTEngine.GetAcceleration()  * TDelta.GetTime()			
	End Method




Leiden(Posted 2005) [#9]
That look about right


Sean Doherty(Posted 2005) [#10]
It doesn't seem right?

DefData 0.75, 200.0, 4.00     'fFriction, fMaximumVelocity, fAcceleration


My time is around .01 so I multiplied all the settings above by 10 but the top speed is to high and the friction doesn't seem right?


Sean Doherty(Posted 2005) [#11]
Well I can see why people don't like delta time. I changed my FPS from 85 to 30 and all the colision detection went nuts?


Leiden(Posted 2005) [#12]
You just need to set it up properly. It can be tricky but the outcome is well worth it. Basically anywhere where something is moved should be multiplied by the delta. Double check your code :)


Sean Doherty(Posted 2005) [#13]
I also noticed that my program is locking with the delta and the framerate set to 30 fps. I have a try and catch with a end but nothing seems to be happening?

Anyway I can dubug the crash?


Tibit(Posted 2005) [#14]
Don't set the FPS to 30! With delta time you can as well have it at 200 or something..

I think that the point you have missed is that when you use delta time, your velocity will be measured in pixels per second.

For example,

Before you had:
Speed:+ 5
@60 FPS that would mean you add 300 to speed every second!
@75 FPS it would be 375.
@200 FPS it would be 1000!

If you have three people playing with these framerates they would all have a very different playing experience (if none at all).

With Delta time you do:
Speed:+ 5 * TDelta.GetTime()

That means you add 5 every second. See in the above example, that would refer to playing the game at 1 FPS, compared to your previous standard.

Speed:+ 5 * TDelta.GetTime() with 30FPS would mean that you add 5 every second.
Speed:+ 5 * TDelta.GetTime() with 75FPS would mean that you add 5 every second.
Speed:+ 5 * TDelta.GetTime() with 300FPS would mean that you add 5 every second.

In other words you have a FPS in-dependant game and your speed is measured in pixels/sec

If your screen is 600 wide and you want to travel it in 5 seconds you speed would be 600/5 = 120pixles/sec. (Quite slow)

You need to change your speeds to something like 200pixels/sec or 500pixels/sec.

This does not only apply to speed but to anything you would normally add:+


Sean Doherty(Posted 2005) [#15]
Wave,

I uderstand the concept and what you provided was a good summary. I only set the framerate at 30 so I could debug an issue that was occuring at a slow framerate.

However, when I changed the framerate to 30 I discovered a possible bug is ImageCollide2 and of course a number of problems being caused by collision detection.

Here is a question:

How do you deal with object colision where the object bounce off one and another? For example. if an object moves right four pixels and there is a collision you can move the object left 4 pixels. However, if you throw delta time into the picture it now becomes a problem since the speed at collision may not be the same as the speed of the frame during the collision.


Tibit(Posted 2005) [#16]
I fail to see the problem.

Imagine your ship traveling at 200pixels/sec. Boom, it hits a wall. Not good. We are now 34 pixels into the wall. This can't be allowed so we move 34 pixels back. The result is that we never pass through the wall - we slide against it.

If you would move us back 34*2 pixels instead you would bounce of the wall. When you bounce you also need to reverse your velocity. Same thing - we never passed through the wall, we bounced off it.

the speed at collision may not be the same as the speed of the frame during the collision.

What does the FPS has to do with our object's speed if you use delta time?

I guess I missunderstand you somehow. Unforunatly I'm going away over the weekend, back monday. I hope you solve it and perhaps someone else can help you til then, good luck!


Sean Doherty(Posted 2005) [#17]
I seem to fix the collision detection and everything is working fine with one exception. There seems to be a difference in the rotation velocity when I set the game to 30 FPS and 85 FPS. I must not have the delta time in the right place?

Have a look at the code and see if you have any advide:


TurnSpeed:-TurnAcceleration * TDelta.GetTime()
		
'Limit TurnSpeed
If TurnSpeed < -TurnMax TurnSpeed = -TurnMax

'Apply Friction To Rotation
If TurnSpeed >  TurnFriction   
TurnSpeed:- TurnFriction * TDelta.GetTime() 
End If           
		
If TurnSpeed < -TurnFriction
TurnSpeed:+ TurnFriction * TDelta.GetTime()
End If
		
'If Friction is Greater than Speed Then Stop
If TurnSpeed < TurnFriction and TurnSpeed > -TurnFriction TurnSpeed = 0


Thanks


Grey Alien(Posted 2005) [#18]
your limits i.e. TurnMax and TurnFriction have to take the Deltatime into account, they can't be constant at different frame rates.


Sean Doherty(Posted 2005) [#19]
How do I do that? I tried?


Tibit(Posted 2005) [#20]
It looks correct to me. You can try to make a simpler demo of your game/engine and test only rotation, perhaps you have some other variable affecting the rotation that you haven't considered?

Can you post some runnable code/demo?

your limits i.e. TurnMax and TurnFriction have to take the Deltatime into account, they can't be constant nomatter the current frame rate.
I can't agree. Max values and Friction Max/Min should be constant over framerates and measured in pixels/second. Ex your engine's topspeed is = 400 (pix/sec). No delta here.


Dreamora(Posted 2005) [#21]
when you do
TurnSpeed:-TurnAcceleration * TDelta.GetTime()

do the same for TurnFriction and other movement defining things "constants"

You do it after the > check which is useless as TurnAceleration was already far to large because of the missing delta time correction.


Grey Alien(Posted 2005) [#22]
Can TDelta.GetTime() ever return 1 or greater? If so the line "TurnSpeed:- TurnFriction * TDelta.GetTime()" could reduce turnspeed to 0 or less in a single calc which is surely not the desired effect?


TartanTangerine (was Indiepath)(Posted 2005) [#23]
Try this module :-

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

Also has examples to limit the render speed.


Grey Alien(Posted 2005) [#24]
Sean Doherty: A similar problem cropped up to this a while ago with someone implementing gravity, they found that it was different when running at different FPS and it shouldn't be. Be interested to see your final solution and what the problem was.


Sean Doherty(Posted 2005) [#25]
Thanks Everyone,

I am out of town this week and don't have access to my source code. I try to post some code when I get home on Friday.


Sean Doherty(Posted 2005) [#26]

Change this following line of code if you think the FPS is going to get lower than you set it. Example : If you set the FPS at 35 then change this to "2" then the FPS can go as low as 17.5 and things will run okay.

If Delta > 1 Then Delta = 1 ' Delta should never be bigger than 1.



Tim,

I don't understand the above line? If this boundry is hit the game will be running at a different speed than intended?


TartanTangerine (was Indiepath)(Posted 2005) [#27]
Yeah thats old code sorry, delta can be bigger than 1 but you want to cap it at say 4 just in case you get a glitch and everything then flies off the screen at a million miles an hour.


Sean Doherty(Posted 2005) [#28]
The following url is a sample program that can be used to look at delta time:

www.FreelanceGames.com/Files/Spin.zip

Just change swap lines to go between 85 frames per second and 30 frames per second.


'Graphics kScreenWidth,kScreenHeight,32, 85
Graphics kScreenWidth,kScreenHeight,32, 30


Generally, the 30 PFS prgram seems to spin the object faster. When the object spins 270 degrees the time will be printed in the ide.

Thanks


TartanTangerine (was Indiepath)(Posted 2005) [#29]
marginally faster and I think I know why.

Did you notice that when the program started the object rotated quickly and then slowed down? that's because when you initialised delta time the very first couple of readings you get will be off the scale due to other things getting intialised.

I put this in the loop and all is fine :D
If pTDelta.DeltaTime > 1 Then pTDelta.DeltaTime :- 1



Sean Doherty(Posted 2005) [#30]
Ok, I just reliezed that there was a problem with the program. The framerate was not being constranded by the Graphics command. I modified the flip parameters and it is working now.

As you can see there is a hugh differenence in the rotation speed of 30 and 85.

www.FreelanceGames.com/Files/Spin.zip

Also, Tim I added you code to the main loop.


TartanTangerine (was Indiepath)(Posted 2005) [#31]
Actually that code I posted is wrong.
If pTDelta.DeltaTime > 4 Then pTDelta.DeltaTime = 4 'Just caps the stuff


You must have some issues with your timing code. Did you try my delta code at all?


Tibit(Posted 2005) [#32]
I took at look at your code, I'm sorry I coudn't figure out the reason. Tough with rotaion_friction = 0 it works. Somehow when you add friction something goes wrong?! Try to set friction = 0 and see. Of course that is not a final solution but it might help you find out whats wrong.


Sean Doherty(Posted 2005) [#33]
Please test this for me:

www.FreelanceGames.com/Files/Spin.zip


Matt McFarland(Posted 2005) [#34]
I can't seem to get Delta working. When I added Wave's code, and put * Delta.Time() in front of things everything runs very very slow. I must be missing something that sets the update frequency?


Matt McFarland(Posted 2005) [#35]
Why is Sean's Delta.Time (DeltaTime * 10 * 10) and Wave's is not?


Matt McFarland(Posted 2005) [#36]
When I do * 10 * 10 it works fast but it doesn't seem to really be going by any framerate what-so-ever.


Matt McFarland(Posted 2005) [#37]
Ok it is affected by the framerate.. I get it now, but do game timers need to be * Deltatime too?


Sean Doherty(Posted 2005) [#38]
No, but it depends what you are doing. If you want something to happen every 10 seconds you do not need delta time.

PS: I never really found delta time to be that smooth. In the end I went with "Fixed Variable Delta Time Stepping".


Matt McFarland(Posted 2005) [#39]
Ok, I have a warp part that is totally screwed up.

At the beginning of a level WarpTimer goes up by 1 every refresh

when warptimer = 100 then it stops warping

when I did delta timing it totally screwed up the way it looks and it warps for a lot longer.


Matt McFarland(Posted 2005) [#40]
Hmm, I have timed events but they're timed on how many refreshes occur.


Sean Doherty(Posted 2005) [#41]
You need delta time for that kind of timer,

warptimer :+ 1 * dDeltaTime
if warptimer >= 100
'do something
end if


Matt McFarland(Posted 2005) [#42]
ok so not

if warptierm >=100*dDeltaTime ??


Sean Doherty(Posted 2005) [#43]
No, I think your good without delta time on the condition.


Matt McFarland(Posted 2005) [#44]
Function DoLevel1()
		CreationTimer:+1
		If CreationTimer > CreateMarker+20
			CreateCounter:+1    'Increase Counter to know which enemies to make
			CreateMarker:+20    'Increase Marker by 10		
	
			If CreateCounter => 10 and CreateCounter < 22 
				TEnemy.Create(32*(3+CreateSubCounter)+16,32*2,3,0,1)
	            CreateSubCounter:+1		
			EndIf
			If CreateCounter =60 CreateSubCounter = 0
			If CreateCounter => 60 and CreateCounter < 72 
				TEnemy.Create(32*(3+CreateSubCounter)+16,32*3,4,0,1)
	            CreateSubCounter:+1		
			EndIf
			If CreateCounter > 90 CreateSubCounter = 0
			If CreateCounter => 90 and CreateCounter < 96
				TEnemy.Create(544-(32*(6+CreateSubCounter))+16,32,3,2,1)
	            CreateSubCounter:+1		
			EndIf
			If CreateCounter > 122 Then CreatePhase = 5
    		
		End If
	
End Function


That is Count sensetive, but its NOT time sensetive, meaning its important the numbers are integers and not floats. This creates the enemies and it also does use the creationtimer INT to determine when to create each batch so therefore would I need to delta-time it and if so how?????


Matt McFarland(Posted 2005) [#45]
Ok BASICALLY

Once I add DELTATIMING into all the Movements, bullets, etc the other parts have to be TIME based and NOT Refresh based?


Sean Doherty(Posted 2005) [#46]
Yes,

You need to add delta time to anywhere you use counters, acceleration, movement, friction. and more. You do NOT need delta time if you have a timer. For example, every 2 seconds you print "Hello World".


Matt McFarland(Posted 2005) [#47]
Delta time converts "flip" or "step" counters into Time based units, but the results are strange, because when the counter reaches 600 on a flip based method it is fast, but when I apply delta timing it is slow, which changes the way the game behaves.


Sean Doherty(Posted 2005) [#48]
Thats why you multiply by 100 (10 *10) or what ever factor you need to make the game run at the correct game play speed. Basically, if you were moving one pixel per update before, you still want to move 1 pixel per update.

So basically, you multiple your delta time by whatever it takes to get that close to one. It will be different every update, but you want it close to 1 as possible most of the time.


Matt McFarland(Posted 2005) [#49]
If I make my game creation timner (which is based on flips) based on delta time and if it results in taking 10 seconds to create the level will it take 10 seconds on every computer?


Matt McFarland(Posted 2005) [#50]
And what about having objects follow a bezier curve? How do you apply Delta Timing to that?


Sean Doherty(Posted 2005) [#51]
I am not sure what your asking but you can test it on you machine with the following changes:

Graphics kScreenWidth,kScreenHeight,24, 85
Graphics kScreenWidth,kScreenHeight,24, 60
Graphics kScreenWidth,kScreenHeight,24, 30
Graphics kScreenWidth,kScreenHeight,24, 12

Flip

By using different graphic modes and flip not bound to the VSync you agem will run at different speeds depending on which line you run when you create the graphics mode


Matt McFarland(Posted 2005) [#52]
Ok now if I set it at 30 and the bullet doesnt move smoothly (because its at a low frame rate) is collision detection not going to work because I have it set "if bullet x is enemy x and bullet y is enemy y blow up enemy" now that idealism wont work with delta timing will it? (because the jerkiness can cause the image to not be drawn near the enemy therefore x and y is different?)


Sean Doherty(Posted 2005) [#53]
The slower the framer ate the larger the delta time and therefore the larger the jump per update. If the jump is to great your collision detection will fail because it will jump right over the object it was going to hit!

Also, I just found it ws to jerky so I implemented "Fixed Variable Delta Time Stepping".


Matt McFarland(Posted 2005) [#54]
Well, that sounds even harder than what I'm doing!!! Please, tell me what I should do.. I am wondering if I should use your "Fixed Var Delta Time Stepping" if that will prevent that... Because at 30fps the game would be unplayable.

Delta time is not same as "Frame Skipping" is in Emulators.


Matt McFarland(Posted 2005) [#55]
How many milliseconds are in a second? 1 million?


Sean Doherty(Posted 2005) [#56]
See if this makes any sense:

Const kDeltaTime:Double = 0.01 

Repeat' - - - - - - - - - - - - - - - - - 

	Try	  
	
		Local dNewTime:Double = MilliSecs() * 0.001
		Local dDeltaTime:Double = dNewTime - dCurrentTime
		If dDeltaTime > .25
			dDeltaTime = .25
		End If
		dCurrentTime = dNewTime

		dTimeAccumulator :+ dDeltaTime	
	    lFrameAccumulator :+ 1
	    
	    If (lFrameAccumulator = 20)
	    	
			dSmothDeltaTime = dTimeAccumulator / lFrameAccumulator	    	    
	        dTimeAccumulator = 0
	    	lFrameAccumulator = 0
	    End If
	    
        
	    dDeltaTime = dSmothDeltaTime
	    
		While (dDeltaTime > 0)
	        
	        dTimeStep = dDeltaTime   
	        If (dTimeStep > kDeltaTime)  
	        	dTimeStep = kDeltaTime	 
	        End If 
	        	        
			'Process a Game Turn
			pTReferee.ProcessTurn(dTimeStep*100)
		    
			dDeltaTime :- dTimeStep
			
		End While    

		'Render the Turn.
		pTReferee.RenderTurn()
	
	Catch ex:Object
		Print ex.ToString()
		End
	End Try

	'Flip 
	Flip 1
	Cls 
	
	
Until KeyHit(Key_Q)



Tibit(Posted 2005) [#57]
The prefix milli( m ) is equal to 1/1000

So ONE Milli second = 1/1000 Seconds
1000 Milliseconds is = 1 Second

And if you add delta time, and notice your games runs slower, it is most likley to have something to do with the speed of your objects.

For example,

Before DeltaTime :
ShipSpeed = 5
This means: Move 5 pixels every frame, if your FPS is 60 then, the actuall pixels/sec that you move is = 5*60 = 300pixels/sec.

After DeltaTime (no change to the ShipSpeed Variable )
ShipSpeed = 5
This means: Move 5 pixels every SECOND, if your FPS is 60 then, the actuall pixels/sec that you move is = 5pixels/sec. Much slower than 300pixels/sec. If however your FPS is 30, and you use delta time, your actuall Movement will still be 5pixels/sec. (still very slow)

So you take and change your ShipSpeed to 300 pixels/sec and your game speed should be the same as before you added delta-time. (Of course this should be analogus to all speeds and accelerations ;) )

However if you have problem with delta-speed not being the same at different FPS then that is a bug/error.

And jerkyness should only be visable if your FPS is very low. 30 FPS should work, Though if your computer is so slow you need to run the game in 30fps, isn't it better to simply increase the Min-Req (run at 60 as min) or try to optimize the code to make the game run faster?

And the reason I do not multiply my delta time with x100 or something is because I want the speed in pixles/seconds, not 100pixles/second - where a speed of 5 would really mean a speed of 500. That seems only to bring more confusion into the mix to me.