Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Discussion / Proper timer based system

Author
Message
Satchmo
21
Years of Service
User Offline
Joined: 29th May 2005
Location:
Posted: 10th Oct 2008 03:34
Now I've gotten to the point where I must make sure everything runs at a good speed at any fps, so I tried putting in a timer based system, but it wasn't a very accurate one and wasn't very smooth. How would I go about implementing a very accurate(and smooth) timer based system? I really don't want to just cop out and not use one all together.

BN2 Productions
22
Years of Service
User Offline
Joined: 22nd Jan 2004
Location:
Posted: 10th Oct 2008 03:58
You could always count using something like this:


This should reset the timer variable every second.

Ever notice how in Microsoft word, the word "microsoft" is auto corrected to be "Microsoft" but "macintosh" just gets the dumb red underline?
Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 10th Oct 2008 12:18 Edited at: 15th Oct 2008 17:27
@satchmo
In my opinion, create your program and run it at what you consider the ideal fps that your program should run. Maybe it's 20, maybe it's 100. Once you have decided what your program should run at, and have tested it and see that it is as beautiful as you hoped, that will be your cap or your ideal FPS. You will still use a timer, but use it to help manage any machines that may run slower, it's not necessary for the faster ones. Assumingly, the faster ones will already be able to run your program at the rate you consider ideal and therefore should look and run the way you hope; so there wouldn't be any necessary use of a timed flow modification in those situations beyond setting the sync rate to your ideal.

There's a couple of ways to approach it. You can use TIMER() to check if a certain number of ms have passed and then force a jump to your subroutines and a sync. This can be a bit tricky. This method works better if you are trying to slow down a faster processing machine.

You can also figure out a percentage of ideal fps versus the actual fps the machine is running at

ideal/actual = some percent

You can take that percentage and multiply it times your movement increments. So if your ideal fps was 60 and the actual rate the machine was running at was 30, you would have a value of 2 to multiply times your movement increments.

So, in general you can achieve pretty good results if you use a combination of the two methods. Keep track of a timer and let's say, every 16 ms (about 60 fps) in the main loop you jump to your movement routines. Before the jump you've calculated the percentage of movement increase to apply to your objects if the fps is lower than the ideal. If the FPS is higher (though it shouldn't be because you set your program to a capped rate - but if you decided to let it run with the sync rate at 0), you don't want to make any adjustments to the movement by applying a percentage because your timing would be taken care of by the 16 ms check, keeping the program running at a consistant fps.

If the computer that is running your program is just too slow, there's not a lot you're going to be able to do and even though you may get the program to do stuff at the right time, the stuff in between the right time can be choppy.

You can figure out the ms you want to run your program at by dividing 1000 by your ideal frame rate. For example, 60 FPS comes out to

1000/60 = 16.7ms



Enjoy your day.
Satchmo
21
Years of Service
User Offline
Joined: 29th May 2005
Location:
Posted: 11th Oct 2008 01:06
I'm not sure I understand, are you saying I should only call my subroutine depending on my program speed? I'm not sure I understand.

Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 11th Oct 2008 02:24 Edited at: 11th Oct 2008 02:29
1. set your program to the fps you want it to run at (your ideal rate). set rate ideal
2. calculate the value of ms that is equal to your ideal sync rate
refresh=1000/ideal
3. retrieve the actual fps the program is running at
actualfps#=screen fps()
4. figure out the adjustment that may be necessary in your movement routines if the actualfps# is less than your ideal
if actualfps# < ideal
adjustment#=ideal/actualfps#
else
adjustment#=1
endif
5. check to see if the number of ms has passed to jump to your routines. Use the command TIMER() as your counter in ms
if timer()-tim >= refresh
gosub routines
tim=timer()
endif
6. inside routines, use the adjustment# to change any speeds
speed#=speed#*adjustment#
7. sync at the end of your main loop ( and inside any loops in your routines that require an immediate visual update - though this may throw the actual sync rate off)

That's the basic idea. If you do a test ahead of time and find out the actual fps is >= to your ideal within a tolerence (maybe +- 2 to 4 fps), you can skip calculating the adjustment and even the timer check if you want. This will save a bit of processing. The only time you will need those is when the actual fps falls below the ideal outside of a tolerence you decide upon.

Enjoy your day.
Benjamin
23
Years of Service
User Offline
Joined: 24th Nov 2002
Location: France
Posted: 14th Oct 2008 06:28 Edited at: 14th Oct 2008 06:32


It's simpler to just run processing code each iteration, there isn't much point to checking if a certain amount of time has elapsed before performing each separate task (besides, if you handle movement that way it won't be so accurate).

Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 14th Oct 2008 09:01 Edited at: 14th Oct 2008 09:12
Very clean! Wish I had thought of that! So, no matter what the rate, a certain amount of time will pass in the iteration and the movement will be matched to that time - as opposed to forcing the movement within a certain amount of time.

Quote: "besides, if you handle movement that way it won't be so accurate"


Why not?

Enjoy your day.
Benjamin
23
Years of Service
User Offline
Joined: 24th Nov 2002
Location: France
Posted: 14th Oct 2008 22:54 Edited at: 14th Oct 2008 22:59
Let's say you're testing to see if 16m has passed (that's a frame at 60 fps) and then moving an object if it has. At the normal frame rate, that's fine. It works with higher frame rates.

The problem is that it doesn't work at lower frame rates. At 30fps you'd want to be moving objects at twice the speed, but the subroutine/function to do so will only be being called once a frame, meaning you haven't solved the main problem. Moreover, because frame rates aren't exact, if you design code for 60fps, then even if it runs at that speed the movement won't be correct as the time for each frame won't be exactly 16ms.

Also I think you should check out the DBP board more often, as this kind of stuff has been discussed a lot in the past and has become pretty much common knowledge for DBP-ers.

Latch
19
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 15th Oct 2008 18:13
Thanks.

Enjoy your day.

Login to post a reply

Server time is: 2026-07-05 00:01:42
Your offset time is: 2026-07-05 00:01:42