Wave's~ BlitzMax Tutorial for NG | ~ November, 2015 ~ Version 11
Beginners guide to BlitzMax |
Refreshrate and Delta Time
FPS, Frames per Second is the speed at which your game updates. By default BlitzMax tries to update at the monitors refreshrate. In the Graphics command: Graphics Width , Height ,Depth, Refreshrate. You can specify a refreshrate which BlitzMax will try to follow. If you have a simple game like pong and play it on a very fast computer without any limitation to the refreshrate, that game would be so fast you wouldn't even see the ball. If you try to play a game on a slow system which gives you a refreshrate below the one specified your game will run slow, that's your games minimum requirements.
Put this type into any graphics code:
DrawText "Your FPS: "+FPS.Calc(),10,10 'This goes in main-loop ' FPS_Counter <> Runs and displays the FPS ' -------------------------------------------- Type FPS Global Counter, Time, TFPS Function Calc%() Counter:+1 If Time < MilliSecs() TFPS = Counter ' <-Frames/Sec Time = MilliSecs() + 1000 'Update Counter = 0 EndIf Return TFPS End Function End Type ' -------------------------------------------
You can run at maximum refreshrate (set it free) and with the use of timing control your logic so it stays at the speed specified by you. In this way no matter what system that runs the game it will run with the same speed; Object A will travel to B in the same time. The object will not slow down but with severe lag the object will warp instead. Once you have specified an objects speed in pixels/sec it will always follow that speed no matter the FPS. But to counter, why would you want lag before slowdown? Multiplayer! In multiplayer each client has to run the game at the same speed. After I learnt how delta timing works I would never choose not to use it, unless we're talking about a very small game. Is deltatiming complicated? The answer is no, but it does require you to add a couple of lines of code to your game. If you add delta time you'll also be able to easily change the game speed while keeping the FPS constant which can be good sometimes.
Here follows the Tank example again, this time with DeltaTime. Try to pretend those squares are tanks.
Strict Global Number_of_Tanks = 50 'How many tanks to create? Const RefreshRate = 85 'Hz = FPS 'Const RefreshRate = NOSYNC 'Try this also 'Try to change the Refreshrate to 5,85,300 'This simulation should run at the same speed because 'of delta-timing. At what framerate does it lag at which 'is it smooth? Type MoveObject Field X#,Y# Field Dir% Global DeltaTime:Float Global TimeDelay:Int ' Millisecs() returns int Function UpdateDeltaTime() DeltaTime = ( MilliSecs()- TimeDelay )*0.001 'Delta Timer TimeDelay = MilliSecs() End Function End Type Type Tank Extends MoveObject 'Override the Speed Field in MoveObject Field Speed# = 400/1 ' Pixels / Seconds Field Size%=5 Global TankNumber=0 'The current number of tanks Global TankList:TList 'Draw draws a rect at the tank's X,Y Method Draw() DrawRect X,Y,Size,Size End Method 'Go update the tank's movement Method Go() X:+Speed*Cos(Dir)*DeltaTime Y:+Speed*Sin(Dir)*DeltaTime End Method 'Sets the starting values of the Tank Method SetupNew() Dir = Rand(0,360) X = (GraphicsWidth()/2) Y = (GraphicsHeight()/2) Speed:*Rnd(0.1,1) End Method 'This function Creates a new tank Function Create() 'Create a List if none exists If Not TankList TankList = CreateList() Local NewTank:Tank = New Tank NewTank.SetupNew() TankList.AddLast( NewTank ) TankNumber:+1 End Function End Type Graphics 800,600,32,Refreshrate ' Create a bunch of new Tanks For Local Nr = 1 To Number_of_Tanks Tank.Create() Next Delay 500 Tank.TimeDelay=MilliSecs() While Not KeyDown(Key_Escape) Cls DrawText "Your FPS: "+FPS.Calc(),20,40 MoveObject.UpdateDeltaTime() 'Update for all MoveObjects For Local T:Tank = EachIn Tank.TankList T.Draw DrawText "Number of Tanks : "+Tank.TankNumber,20,20 T.Go 'update Next Flip Wend ' FPS_Counter <> Runs And displays the FPS '------------------------------------------- Type FPS Global Counter, Time, TFPS Function Calc%() Counter:+1 If Time < MilliSecs() TFPS = Counter ' <-Frames/Sec Time = MilliSecs() + 1000 ' Update Counter = 0 End If Return TFPS End Function EndType ' -------------------------------------------
When you want to add DeltaTime you can follow these steps: 1. Add these lines to your main loop.
DeltaTime# = ( MilliSecs()- TimeDelay )*0.001 ' Delta Timer TimeDelay = MilliSecs()
Make sure that DeltaTime and TimeDelay are Globals so that you can use them in your functions and methods. I did it the OO-way in my Tank Example, but feel free to just paste this into your mainloop, does the same. Do you wonder why I multiply DeltaTime with 0.001? This is because millisecs() measures the time in milliseconds, 1000ms is one second. You probably want to measure your speed in seconds. That is pixels / seconds instead of pixels / milliseconds, that's why you divide DeltaTime with 1000 or multiply it with 0.001. Also make sure DeltaTime is a Float or Double! And that TimeDelay is an int.
2. To all variables that change over time, that is Speed, Acceleration, Shield generation, Energy Recharge. Multiply them with DeltaTime.
X:+Speed*Cos(Dir)*DeltaTime Y:+Speed*Sin(Dir)*DeltaTime Sheild:+ SheildRechargeRate*DeltaTime
Make these variables are floats or doubles. 3. Redefine your speed. When using deltatime your speed is measured in pixels/second. This means that if you have a resolution of 800x600 and you want to travel the screenwidth in 3 seconds. Your speed would be = 800/3, 800 pixels in 3 seconds. That speed will be the same no matter the frame rate. Here is my Delta-Type. It will help you with delta time. No excuse not to use it now =)
' _____________________________________________________ ' ------------------------------------------------------ Type Delta ' D E L T A T I M E ' ----------------------------------------------------- ' This type is Fully global. Which means you'll always ' refere to it as Delta.Start() , Delta.Time(), ' Delta.Update() ' ' You shouldn't create instances of this type! ' DeltaTime is the same for all your objects! ' Global DeltaTime# Global TimeDelay% ' Do this before your main loop ' If you don't there will be a jump in deltatime ' where it is very big until it cools down ' If anything is moving under that time it would get speeds ' well above 100000. So put this line before your main-loop Function Start() TimeDelay = MilliSecs() End Function ' Everytime where you want to get the deltatime ' call this: Delta.Time ' You should add this to every place which ' adds to your position/speed/acceleration ' But not to everything that adds ' ' The basic rule is to add deltatime to all ' things which get added to every frame (over time) ' because this means they will get huge if ' you don't use delta. ' Like Speed:+ 10*Delta.Time Function Time#() Return DeltaTime# End Function ' Put this once in your main loop ' it calculates the current deltatime ' depending on your framerate or more exact ' the time between each/the last frame. Function Update() ' _____________________________________________________ ' Purpose: Calculates DeltaTime , put it in mainloop ' ---------------------------------------------------- DeltaTime = ( MilliSecs() - TimeDelay )*0.001 TimeDelay = MilliSecs() End Function End Type '_____________________________________________________ '------------------------------------------------------
To Index | Next Page | page 18