Limiting the frame rate, if v-sync is turned off.

BlitzMax Forums/BlitzMax Programming/Limiting the frame rate, if v-sync is turned off.

WERDNA(Posted 2010) [#1]
I recently uploaded the demo for my newest game, Ping Pong Battle, and for
the most part it works fine. For those who have their graphics cards v-sync turned
off however(Looks pointedly at Cygnus ;), the game runs at 200+ FPS which
makes it pretty unplayable.

So what I'm looking to do is to limit the Frame Rate to 60.
I'm pretty sure this code works, because I turned v-sync off, then ran the game,
(It ran at 200 FPS), then I inserted this code and played the game again, and it
ran at about 60 FPS.

Here's the code, which is inserted at the very beginning of the Main loop.

Local Time:Float = 0
Local Time2:Float = 0
Local OldTime:Float = MilliSecs()

While InGame = 1 ' << Main Loop
Repeat
Time2 = MilliSecs()
fps = fps + 1
If Time2 >= OldTime+1000/60
Time2 = 0
OldTime = MilliSecs()
Time = 1
End If
Until Time = 1
Time = 0

'Other game stuff, draw images, update characters, etc.
Wend


If there is a better way of doing this, please let me know ;)


Midimaster(Posted 2010) [#2]
to save performance and resources on your computer it is important, that the programm gives up control during waiting to the operation system.

one way ist to use a timer:

frameTimer = CreateTimer  (60)
Graphics 640, 480

While Not KeyHit (1)
   CLS
   ; graphical things here...

   WaitTimer (frameTimer)
   Flip 0
Wend


With this, the operation system jumps back into your program exactly 60x per second. There is also a second possibility with the DELAY command.


WERDNA(Posted 2010) [#3]
I tried the timer, but it runs too quickly with v-sync turned off. I need something
like what I have in my above post, that will limit it EVEN IF v-sync is turned off.

Thanks though :)


Midimaster(Posted 2010) [#4]
How could this be?

The TIMER is not depending on a vsync signal... with a CreateTimer(60) you get exactly 60 jump in's.


The program CANNOT run faster then 60fps with this code!


Muttley(Posted 2010) [#5]
Timer method is one way, but also have a read of this: Fix Your Timestep


WERDNA(Posted 2010) [#6]
Oh, maybe I wasn't using the timer right, lol.

Taking a look at the link now Muttley :)

Although all I really need to know, is if the code I wrote above is 'good enough', so
that I can just get on with it and upload a new Ping Pong Battle demo :)


Midimaster(Posted 2010) [#7]
The code you wrote above is a hardware stressing catastrophy.

You will have 100% system performance without doing nothing. It is as bad as a...
For I=0 to 10000000
Next
...loop to burn time. You can see the performance with the windows task manager

And it is not very exact. On my computer your code jumps out of the repeat loop after much more than 16msec. I added a PRINT command to see the differences of time

...
         Time = 1
      End If
   Until Time = 1
   Time = 0
   Print oldtime
   'Other game stuff, draw images, update characters, etc.
Wend


and got:
305408.
305472.
305536.
305600.
305664.
305728.
305792.
305856.


as you can see there are more than 60msec between the steps. this is a fps below 20!


You target should be, to give resources back to the system if you do not need them. The link Muttley offers does not reduce the frame rate to 60, but resizes all movements in your game to use the maximum frame rate of a computer.

There are two possibilities:

1.
reducing the framerate to 60. All movements do fixed steps in the game
PlayerX=PlayerX+2.4


2. Resizing steps to framerate
PlayerX=PlayerX+2.4*60/fps


The system 2 is much more intelligent and can also be used on computers, which would be to slow for 60fps. But for most of the games system 1 is good enough. And is it not stressing the computers hardware.

To optimize your code I would suggest to add a DELAY command. This jumps back to operating system for a certain time and returns back to continue your game:

Global OldTime%
ingame=1
While InGame = 1 ' << Main Loop
	Repeat
		Delay 1
	Until MilliSecs()> OldTime
	Print oldtime + " " + MilliSecs()
	OldTime=MilliSecs()+15
	'Other game stuff, draw images, update characters, etc.
Wend


The performance is below 5% and the result are 16-17 msec each turn:
765409
765425
765442
765458
765475
765491



WERDNA(Posted 2010) [#8]
Thanks Midimaster!

The code, and advice will help out tremendously :)