Frame limiting
BlitzMax Forums/BlitzMax Programming/Frame limiting
| ||
A search of the B'max forum isn't bringing up much, anyone have some nice frame limiting code? |
| ||
I go with delta timing.I posted my code over at codersworkshop. |
| ||
Got a link to it? Cheers Tom |
| ||
Heh, I'll post it hereType DeltaTime Global DeltaTList:TList Field OldTime:Double Field ElapsedTime:Double Field Delta:Double Field dFps:Double Field dDelta:Double Field CurrFps:Double Field FPSCounter:Double Field CurrTime:Double Field CheckTime:Double Method New () If DeltaTList = Null Then DeltaTList = New TList DeltaTList.AddLast Self End Method Method Destroy () DeltaTList.Remove Self End Method Function Create:DeltaTime(Fps:Double) Local dTime:DeltaTime = New DeltaTime dTime.Delta = 1 dTime.dFps = Fps dTime.dDelta = 1000/Fps Return dTime End Function Function Update() Local dTime:DeltaTime For dTime:DeltaTime = EachIn DeltaTList dTime.CurrTime = MilliSecs() dTime.ElapsedTime = dTime.CurrTime - dTime.OldTime dTime.OldTime = dTime.CurrTime If dTime.CurrTime > dTime.CheckTime dTime.CheckTime = dTime.CurrTime + 1000 dTime.CurrFps = dTime.FPSCounter dTime.FPSCounter = 0 Else dTime.FPSCounter:+1 EndIf Next End Function Function FPS(dTime:DeltaTime) Return dTime.CurrFps End Function Function CurrDelta:Double(dTime:DeltaTime) Return dTime.ElapsedTime/dTime.dDelta End Function End Type |
| ||
Any chance to show how it work ? |
| ||
Tom - If I remember correctly, you are using 'ball physics' in one of your games - delta timing doesn't work well at all with these types of games - gives wildly different results on different machines and you will need a logic loop that executes at a fixed rate on all machines to make something reproducable. |
| ||
Example: Set Your Globals Global Delta1:DeltaTime = DeltaTime.Create(35.0) ' Normal 35 FPS Global Delta:Double Now Main Game Loop While Not EXIT_FLAG DeltaTime.Update() Delta = DeltaTime.CurrDelta(Delta1) If Delta > 1 Then Delta = 1 ' Delta should never be bigger than 1. ' -------------------------------GFX FUNCTIONS --------------------------- ScreenUpdate = ScreenUpdate + Delta ScreenX.Update(Delta) If ScreenUpdate > 0.30 Then RenderGFX() ScreenUpdate = 0 Timer.UpdateAll() EndIf ' ------------------------------------------------------------------------ UpdateGame(delta) ActiveChannel.UpdateAll() FlushMem Delay(1) Wend Multiply all movements and animations etc by Delta. |
| ||
Many Thanks |
| ||
Hi try to modify this code but it's strange the blob don't move ? |
| ||
Ah okay, sorry you need to multiply the amount you want the object to move by Delta. Also you need to make your bx variable a double. See below |
| ||
In fact your code should really be this since you are not rendering the gfx every frame, only when screenupdate reaches a certain threshold. You need to pass screenupdate as the delta. |
| ||
Ok !! thanks :) but i have a little question ? this piece of code can be compared with tweening method ? Because if i change : Global Delta1:DeltaTime = DeltaTime.Create(35.0) ' Normal 35 FPS With Global Delta1:DeltaTime = DeltaTime.Create(10.0) ' Normal 10 FPS The circle move more slowly ? it is normal ? If 'im remember the blitz3d tweening method the object move in the same distance/time with more or less FPS ? |
| ||
That command sets the Frame Rate, all delta time will be based off of that rate. Once you have set the rate all object movement will be exactly the same regardless of the speed or the machine it is running on. To demonstrate this put a random delay in your loop and see what happens. Delay Rand(1,20) |
| ||
Nice code. I've since come to realise that at certain FPS rates (when the drawing rate drops low) then things are gonna get juddery and there's nothin you can do about it really. i.e, if the monitor refreshrate is 85 and the draw rate drops to 60 fps, then 25 of those 60 frames will be displayed twice during the monitors 85 refreshes. That's the problem I was having but not understanding til now. Of course it's gonna be rare that drawing drops that low so it's not too big a deal after all. Tom |
| ||
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. |
| ||
Hi Videogame Takeaway I have two questions : - I'm obliged to use alway double value ? like this : MySpritePX:Double=10 .... MySpritePX=MySpritePX+1*Delta .... It is correct ? - I don't understand very well the line : If ScreenUpdate > 0.30 Then Can you clarify ? I notify a strange stuff : when i want to know the FPS with : DrawTex DeltaTime.FPS(Delta1),10,10 This return some strange value between 60=>145698=>65=>300 etc ? when i open a screen with the NOSYNC flag, any idea ? or i must use a constant refresh rate, like 60 ? Cheers |
| ||
Hi Filax, Use floats or doubles, your choice but never Ints. - I don't understand very well the line : If ScreenUpdate > 0.30 Then Based on the Frame Rate I set earlier in the code this line forces a screen update about every 60th of a second and prevents a screen update occuring every computational frame. The FPS reported is actually the speed of each computational frame, remember graphics are only rendered when Screenupdate > 0.30 Does this help? probably not, I'm tired and full of beer. Ask me again if you need me to explain. PS. Call me Tim. |
| ||
PS. Call me Tim (not Videogame Takeaway). Bring back Indiepath I say - know who you are then. ;-) |
| ||
Na, that would be boring. |
| ||
lol Tim :))))))))))) Drink another beer for me :) i understand now :) thank !!! |
| ||
Tim The last question, it's a fault if use use a NOSYNC graphics screen ? |
| ||
Please use NOSYNC, it allows the logic to update without waiting for the vSync Signal. This is particularly good for physics applications where you need a fast logic update but only want to actually draw to screen when needed. |
| ||
Oh, thank for reply :) but when i'm making a screen with NOSYNC parameter the function Function FPS(dTime:DeltaTime) return a strange number between 60=>1235718 ?? Try this : |
| ||
This is excellant code !! :) awome stuff :) can I ask why you use a list for delta time type ? Why would one need to add more delta time types into a list ? or is that only on "new" Sorry for the noob questions. |
| ||
Yes, I get that too. It's reporting the actual speed of the game loop and not the Amount of Renders Per Second. The reason being that we've told the application to only render to screen when the ScreenUpdate variable reaches a certain threshold, thus we already know what the maximum amount of rendered FPS will be. If the Rendered FPS dips below the ScreenUpdate threshold then it will be reported as Rendered FPS and not number of application loops per second. If you take out the ScreenUpdate checks then you will get the REAL ACTUAL Rendered FPS. Oh and I recently updated the Delta code, it's a lot more accurate now and faster :D @Deux, I use this method as it's good OOP practice, it keeps everything nice and neat. I may also need multiple Delta Timers controlling different things - this code gives me the flexibility. |
| ||
Hi Tim :) Nice piece of code :) but i have another question (no ! don't kill me !! PAN !) What this method ? Method SetFPS(NewFPS:Float) Self.dFPS = NewFPS Self.dDelta = 1000/Self.dFPS End Method |
| ||
Arrrgghhhhhh... LOL This allows you to dynamically adjust the game timing. For example, you initialise the timing with:- Global Delta1:DeltaTime = DeltaTime.Create(35.0) You code your game objects and animations based on that setting (35.0). Now lets say you want to dynamically speed up or slow down the whole game. You can affect the whole game speed by setting the new FPS (maybe wrong name for function but who cares). I do this to great effect in GEOM, when you get a SLOWMO powerup the game speed is 50% of normal ie. SetFPS(NormalSpeed/2). Cool eh? |
| ||
One more thing.... You may like to know that I put the IGlass update command in the ScreenUpdate portion of code in my new application and it still works fine. The benefit being that IGLass updates are only done at each screen render and do not affect the game logic speeds at all. ' -------------------------------GFX FUNCTIONS --------------------------- ScreenUpdate :+ Delta If ScreenUpdate > 0.5 Then ScreenUpdate :-0.5 Parse_Render_States() IGL_RefreshGui() EndIf ' ------------------------------------------------------------------------- |
| ||
Ok ok !! very interesting !!! Many thanks to reply :) |
| ||
I'm trying to make a little template for using simply your delta code : The template : Here is the include : Inc_Delta.bmx If you find some error tell me ! Cheers |
| ||
Looks okay to me BUT I have not tested it. |
| ||
'Identifier destroy not found' Should it be my_appdelta.destroy() ? |
| ||
Tonyg it's ok now :) |