PDA

View Full Version : Framerate problems



s.c.s.i.
01-09-2004, 06:33 AM
Hi,

This is my first post here, and I am very happy to have found a place where I hopefully can get some help with solving my problem. I just started using DelphiX a few dags ago, although I have been using Delphi for many years.

My problem concerns framerate, and having searchd the net for an answer, I have found that this is a common issue, although it seems somehow ignored.

My "game" is coded within a DXTimer.OnTimer event. All the tutorials I have found on the subject say that I should put the timer interval to 0 or 1, to get as many fps as the computer can render. But they compleatly ignore the fact that not every computer is of the same hardware as the one the game is being developed on.

The first thing, that I hope you could explain to me, is this phenomenon:
I get now difference in fps when I set the timer interval to 1 instead of zero, when doWaitVBlank-property of the DXDraw is set to true. I get around 65 fps.
But when I set doWaitVBlank to true, a timer interval of 1 still gives me around 65 fps, but an interval of 0 gives me like 750 fps, and the game runs _extremly_ fast.
Why is that?


My goal is, of course, to make a game that runs equally "fast" on every computer, meaning, the ball should move across the playfield in the same amount of time on a fast computer, as on a slow. The only difference should be that the game runs "smoother" on the fast one. The framerate (fps) must not affect the speed of the game.

Well, I am sure that you understand the problem. I have read somewere that the value LagCount is the key to the solution, but still, it is unclear to me.

Is there any peace of text that covers this, or an example, perhaps?

Thank you in advance
//Daniel

And sorry about my english. I'm from Sweden.

Paulius
01-09-2004, 08:54 AM
Wait for vblank means that flip does not return until the monitor is done drawing the last frame. So if you?¢_Tre monitor is set to 60Hz then the most FPS you could get is 60. The good thing about it is that in this way you don?¢_Tt get tearing (the effect which comes from having part of the last and part of the current image on screen) but you potentially waist clock cycles while CPU is waiting. If you don?¢_Tt do everything as fast as possible (in your case a timer with a non 0 interval) you might be idly wasting even more time. To get proper movement on all computers you should make all you velocities time delta based (meaning don?¢_Tt do X:= X + XSpeed, but rather X:= X + XSPeed * TimeDelta)

Traveler
01-09-2004, 09:09 AM
Having a value of 0 or 1 shouldn't make much of a difference. It will both make the game run at maximum speed. How fast depends on the pc itself of course. Having doWaitVBlank set to false means that the game will not wait for the monitor's refreshrate, resulting in a higher framerates. This does however come with a price in the form of tearing. This can usually be seen with scrolling.

DelphiX' timer isn't framerate independent (afaik anyway). If you want this, you should look into timebased movement rather than framebased.
There have been questions about this in the past. A quick search should help.

There's a article over at gamedev that should be helpful
http://www.gamedev.net/reference/articles/article1604.asp

s.c.s.i.
01-09-2004, 10:47 AM
I fugured out the basics, meaning, I should multiply all movement with the LagCount-variable, but that isn't enough.

When I design the game, I must know how much to add to X-position, to get a smooth movement, and also, for the ball to travel a specific distance in a specific amount of time. That means that I have to assume a framerate, wich I will use when syncing my game.

What framerate should that be? If I set it to 30 fps, and make my game play as it should be, anything bellow 30 fps would still run ok, since the LagCount-variable will take care of that. But then I am limiting my game to 30 fps, and a monster computer would not get any smoother motion at all, even if it is capable of rendering 150 fps. And this is not too good.


I am just not sure under what circumstances I am supposed to develop the application.



Edit: And one strange thing more: When I set the timer to 0 or 1, I get around 75 fps, but the LAGCount varies. One time-tick it is 1, the next 5 or six, it is 15, then 1, then another set of 15... Is this normal?

cairnswm
01-09-2004, 11:54 AM
Using the lagcount property should mean the same movement on all systems doesn't matter what the frame rate.

For example on 50FPs the lag count = 0.1
with 100 FPS the lag count = 0.05

Therefore for every 2 frames at 100FPS it moves the same distance that it does in 1 frame on 50FPS.

s.c.s.i.
01-09-2004, 12:00 PM
But LagCount is only an integer, and can only be 1 as smallest.

If I develop the game on my computer, wich runs it in 50 fps, and with LagCount=1, a computer running in 100 would have to have LagCount 0.5, right? Than it would be alright. But LagCount is an integer. It cannot be 0.5, as it should be. :?

Useless Hacker
01-09-2004, 12:01 PM
distance = speed * time

i.e. calculate the distance to move your objects based upon the speed you want them to move and the frame time.

Edit: I just realised that Paulius already said this, nevermind.

s.c.s.i.
01-09-2004, 12:07 PM
I realize that I am starting to nag, and I am really sorry about that, but I just cant fully understand the logic behind it all.

Aren't there any examples that demonstrate this, or is it really basic stuff that everyone is supposed to figure out by themselves?

Paulius
01-09-2004, 02:07 PM
If you want to do it delta based then you don?¢_Tt need a timer component at all. Use GetTickCount or QueryPerformanceCounter or whatever every loop to get the time then get time delta by subtracting last time value from current time value.

s.c.s.i.
01-09-2004, 03:42 PM
Ok, when my timer interval is set to 0, and when using GetTickCount, the delta-value is most often 0, but sometimes between 15 and 30. What do I have to do with this delta-variable, in order to be able to multiply my movements with it?

Divide by ten? :P


Edit: And of course, it mustn't be 0. I should just skipp the multiplikation when it is zero, I guess?

Useless Hacker
01-09-2004, 05:42 PM
Don't use GetTickCount, it has a very low resolution. QueryPerformanceCounter or timeGetTime are better.

Also, it is better to store positions, speeds etc. as floating-point (i.e. Single/Double) rather than integers.

Damot
02-09-2004, 09:49 AM
Been here myself so I know how confused you are, but it's a lot easier than you think.

You need to write some code to calculate how long it's been since the last frame and move everything based on that.

So if you want something to move at 100 pixels per second, work out how much time has gone by since the last frame and move your character by the appropriate amount.

Don't have access to it now, but if you want some example code, email me
thedamot@mailcan.com

Cheers,


Damot

cairnswm
03-09-2004, 07:40 AM
Here is some source code:

http://www.cairnsgames.co.za/download.asp?file=http://www.cairnsgames.co.za/barbar/barbarsrc.zip

Note however that the way this code works is that it waits until a set delay is complete before moving the sprite - ie it skips some frames if no movement is neccessary.

Look at the Draw functions in UnitBarBar and UnitItems.