Making the Frame Rate stay at 60 ?

BlitzMax Forums/BlitzMax Beginners Area/Making the Frame Rate stay at 60 ?

Captain Wicker (crazy hillbilly)(Posted 2012) [#1]
Hello,

I have been trying to make the frame rate(fps) stay at 60 due to problems with the BlitzMax programs jumping to 300-900fps. Does anyone here know how to keep the fps at 60? Why doesn't Const FPS#=60 work?


matibee(Posted 2012) [#2]
Using "Flip 1" should do. That ties your app to the video card sync rate which is usually around 60 to 100 hz. Don't rely on it for timing your app though.

Const FPS#=60


It does work. It creates a const with the value of 60 just like you asked. But it won't have any bearing on the fps of your game. At least not in Blitzmax it won't.


ima747(Posted 2012) [#3]
The why is more important than the how...

The system will draw as fast as it can unless you limit it. There is no inherent limit, or built in limiting system in bmax. The more important question is why do you want to limit frame rate...

Prevent Screen tearing:
You can limit the frame rate to the vsync rate of the display by using flip(1) instead of flip() (the 1 arg tells it to vsync the flip call to prevent tearing, if it's ommited it's assumed to be 0 and therefore it does not sync) however frame vsync rate is hardware dependent so is not reliable to game timing. It does what it's supposed to, prevent screen tearing, but relying on it for more than that is asking for trouble. Most screens these days are lcds operating at 60hz... but there are 120hz and even 240hz screens. There are screens that operate at 59hz, there are screens that missrepresent their frequency, and then there are CRTs still which can range WILDLY and be configured by the user per resolution... don't rely on vsyncing for game timing, it will be fine on your computer, maybe even all the ones you can get your hands on, but it WILL go wrong for a lot of people in the real world.

Game logic/update speed:
There are a number of ways to go about this. One of the more widely used and my personal preference is tweening. Tweening in essence lets you code to a logical update rate, but then you skew the actual changes by the time between frames. i.e. you set your logic around 30fps, but the game is actually running at double that speed (60fps), by applying the tween value to your change you are only updating half as much per frame (since there are twice as many frames) to make the logic consistent. The nice thing about tweening is that it's fairly easy to understand, works when the frame rate goes above OR bellow the intended frame rate (the game lags for a second because the OS is doing something in the background... game time continues as if the lag didn't happen, it just skips over those frames). Search the forums for more details and implementation examples, as well as alternative methods.

Last edited 2012


H&K(Posted 2012) [#4]
You set-up a message loop, (The sort that you use to run windows), this basicly does nothing most of the time. But when you tell it to do something, (A mouse click, etc, OR a 60 Hertz timer) it will do off do this, then return to the loop.

So every time the timer posts a message on the message que, you know to run you screen/logic. (This is NOT Tweening, but fixed rate)

Last edited 2012


Captain Wicker (crazy hillbilly)(Posted 2012) [#5]
why do you want to limit frame rate

different computers run at different speeds. for say I have an older Win2k system and a newer Win7 system. In order to get the same effect (in this case the frame rate) you would need to either cap the FPS or either the buyer with the older machine would need to upgrade their computer.

EDIT:
I think I have fixed my problem but I have made an example so that I can be sure.
Import sidesign.minib3d


Global app_name$ = "Demo Game V1.1"
AppTitle$ = (app_name$)
Local width = 800 , height = 600 , depth = 32 , mode = 2 , hertz = 60
Graphics3D width , height , depth , mode , hertz


'setup fps start
Local old_ms = MilliSecs()
Local renders
Local fps


DEF_camera = CreateCamera()
DEF_light = CreateLight()
RotateEntity DEF_light , 90 , 0 , 0

AmbientLight 152,152,152


sphere = CreateSphere(32)
PositionEntity sphere , 0 , 0 , 5


While Not KeyDown(KEY_ESCAPE)


	If KeyDown(KEY_UP) = True Then MoveEntity sphere , 0 , 0 , .5
	If KeyDown(KEY_DOWN) = True Then MoveEntity sphere , 0 , 0 , - .5
	If KeyDown(KEY_LEFT) = True Then TurnEntity sphere , 0 , .5 , 0
	If KeyDown(KEY_RIGHT) = True Then TurnEntity sphere , 0 , - .5 , 0
	
	
	
	
	UpdateWorld 
	RenderWorld

	' fps run
	  renders = renders + 1
	If MilliSecs() - old_ms >= 60
		old_ms = MilliSecs()
		fps = renders
		renders = 0
	EndIf
	Text 0 , 0 , "FPS: " + String(fps)
	'done with fps

	Flip(1)
	
Wend

	

Is this correct?

Last edited 2012


ima747(Posted 2012) [#6]
There is nothing limiting the FPS in there ,just trying to calculate it. Additionally if you do limit the FPS you're only caping it (if it's under 60fps it will bog down and run suuuuper sloooow rather than skip frames like tweening, this is the down side to fixed logic which I assume is what you're going for...). If you were to fix it that way you would be burning processor time during the inter frame pause which is generally impolite (on some systems it can cause the processor to run at 100% all the time which generates al of heat, burns battery on laptops, etc.)

I think what you wanted was along these lines
While MilliSecs() - old_ms < 1000/60
Wend
old_ms = Millisecs()

As long as current time - last frame time is less than 1/60th of a second (remember time is measured in milliseconds so 1000 = 1 second...) it will just keep checking to see if that's true, once it's no longer true it will continue on. This is not optimized (so it's easier to understand and read), and a timer would provide a more efficient way to burn off the extra time without roasting the processor. And I would still urge looking into tweening over fixed rate.... if this runs on a system with a slower vsync it will bog down even though the processor can render more. Additionally I would put it after the flip so that you don't get a wait for time, then wait for screen happening which is essentially 2 waits right after each other on different criteria, you want the screen wait to be included in the time wait or else they're independently waited for rather than just waiting for the longest one.


Captain Wicker (crazy hillbilly)(Posted 2012) [#7]
old_ms < 1000/60

What is to be expected from this?
Here is what I have done. I have replaced the old code with this. But now my FPS doesn't show! What next?

	' fps run
	  renders = renders + 1
	While MilliSecs() - old_ms < 1000/60
		old_ms = MilliSecs()
		fps = renders
		renders = 0
	Wend
	Text 0 , 0 , "FPS: " + String(fps)
	'done with fps


Last edited 2012

Last edited 2012


matibee(Posted 2012) [#8]
Look where ima747 put his While and Wend. There's no code between them.


H&K(Posted 2012) [#9]
http://www.blitzbasic.com/codearcs/codearcs.php?code=1721


matibee(Posted 2012) [#10]
Here's my preferred method..

It doesn't matter if vsync is used or not.
It doesn't matter if the update cycle is called in regular intervals.
It doesn't matter if the app is stalled due to the user dragging the window etc.






ImaginaryHuman(Posted 2012) [#11]
Graphics 640,480,60

and

Flip -1

will lock it at 60hz, but without vertical blank refresh sync