Game Timing
BlitzMax Forums/BlitzMax Programming/Game Timing
| ||
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? |
| ||
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 :) |
| ||
That deltatime example wastes a millisecond per frame, does it crash if elapsed = 0? |
| ||
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. |
| ||
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. |
| ||
Ahh I see, my mistake. One day I'll actually nuckle down and try to understand mathematical concepts :S |
| ||
This might help: I hope the comments are still valid. I like having a Delta Type, it really makes it cleaner. |
| ||
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 |
| ||
That look about right |
| ||
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? |
| ||
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? |
| ||
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 :) |
| ||
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? |
| ||
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:+ |
| ||
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. |
| ||
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! |
| ||
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 |
| ||
your limits i.e. TurnMax and TurnFriction have to take the Deltatime into account, they can't be constant at different frame rates. |
| ||
How do I do that? I tried? |
| ||
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. |
| ||
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. |
| ||
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? |
| ||
Try this module :- http://www.blitzbasic.com/Community/posts.php?topic=49306 Also has examples to limit the render speed. |
| ||
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. |
| ||
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. |
| ||
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? |
| ||
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. |
| ||
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 |
| ||
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 |
| ||
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. |
| ||
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? |
| ||
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. |
| ||
Please test this for me: www.FreelanceGames.com/Files/Spin.zip |
| ||
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? |
| ||
Why is Sean's Delta.Time (DeltaTime * 10 * 10) and Wave's is not? |
| ||
When I do * 10 * 10 it works fast but it doesn't seem to really be going by any framerate what-so-ever. |
| ||
Ok it is affected by the framerate.. I get it now, but do game timers need to be * Deltatime too? |
| ||
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". |
| ||
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. |
| ||
Hmm, I have timed events but they're timed on how many refreshes occur. |
| ||
You need delta time for that kind of timer, warptimer :+ 1 * dDeltaTime if warptimer >= 100 'do something end if |
| ||
ok so not if warptierm >=100*dDeltaTime ?? |
| ||
No, I think your good without delta time on the condition. |
| ||
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????? |
| ||
Ok BASICALLY Once I add DELTATIMING into all the Movements, bullets, etc the other parts have to be TIME based and NOT Refresh based? |
| ||
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". |
| ||
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. |
| ||
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. |
| ||
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? |
| ||
And what about having objects follow a bezier curve? How do you apply Delta Timing to that? |
| ||
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 |
| ||
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?) |
| ||
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". |
| ||
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. |
| ||
How many milliseconds are in a second? 1 million? |
| ||
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) |
| ||
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. |