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 Professional Discussion / Best timer based movement routine?

Author
Message
wattywatts
14
Years of Service
User Offline
Joined: 25th May 2009
Location: Michigan
Posted: 17th Jun 2015 22:29 Edited at: 18th Jun 2015 04:06
For a long time I've been using this

(Sorry to whoever originally wrote it, I don't remember and can't give credit).
I'm playing around with a new project and have made everything timer based. After experiencing severe camera "jumpyness" and commenting almost everything out the problem turned out to be the routine above. So naturally I'd like to find the best routine I can and was hoping for some suggestions (I've seen a lot of bickering over what's best and felt that at this stage maybe there's finally a definitive answer).

EDIT
After a lot of forum searching I've learned that Perftimer is much more accurate than Timer, but I really like how easy this particular piece of code is - I've been trying to convert it to use perftimer but it has so far eluded me, so if anyone can offer some help with that I'd greatly appreciate it.

EDIT2
Nevermind, was able to finally wrap my brain around it thanks to this code snippet. http://forum.thegamecreators.com/?m=forum_view&t=177729&b=6
Mage
17
Years of Service
User Offline
Joined: 3rd Feb 2007
Location: Canada
Posted: 19th Jun 2015 14:24 Edited at: 19th Jun 2015 14:28
You must have found my discussion with some guy who insisted "smoothing" (averaging timing values over last 30 frames) was a good idea.

Good on you for seeing you needed more accurate values and not gimmicks.

Just watch out that you aren't introducing stutter by periodically running frames long by doing too much work between frames.

Kuper
16
Years of Service
User Offline
Joined: 25th Feb 2008
Playing: Planescape:Torment
Posted: 19th Jun 2015 22:31
I use this


Derek Darkly
12
Years of Service
User Offline
Joined: 22nd Sep 2011
Location: Whats Our Vector, Victor?
Posted: 20th Jun 2015 01:12
A theory question here...

Aren't these precision timings basically negated by the fact that the program only updates once per loop?

I have on occasion used only my sync rate to time games, and it seems to work just as well.

Perhaps I'm oversimplifying.

Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 20th Jun 2015 16:23
Quote: "Aren't these precision timings basically negated by the fact that the program only updates once per loop?"


@Derek Darkly

Nope, the timings are returned from the clock as the timer functions are called.

@wattywatts

I try to adjust such values by a specific quantity of units per seconds; where I can. So if I need an entity to move 1000 units per second, or 1 unit per millisecond; I call a function which returns how far the entity should move using the time the last movement occured. Works like a charm.

The Matrix1 command HiTimer() is a good timing function which elapses every millisecond (by default); this time counts from zero from when your program starts, not from when the OS timer starts.

Derek Darkly
12
Years of Service
User Offline
Joined: 22nd Sep 2011
Location: Whats Our Vector, Victor?
Posted: 20th Jun 2015 16:56
Quote: "Nope, the timings are returned from the clock as the timer functions are called"


Oh I see.. when he says EVERYTHING he means the syncing is timer based as well, not just the animations, etc.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 22nd Jun 2015 00:39
Quote: "I try to adjust such values by a specific quantity of units per seconds; where I can. So if I need an entity to move 1000 units per second, or 1 unit per millisecond; I call a function which returns how far the entity should move using the time the last movement occured. Works like a charm."


This is what I do as well. it is simple and works very well to ensure that everything changes by the amount they are supposed to for a given period of time.

Mage
17
Years of Service
User Offline
Joined: 3rd Feb 2007
Location: Canada
Posted: 24th Jun 2015 18:28
Quote: "This is what I do as well. it is simple and works very well to ensure that everything changes by the amount they are supposed to for a given period of time."


If I understand you correctly this is a poor way to do things. You basically end up calling a function and calculating each and every time you need to adjust a value for timing.

Instead Timer Based Movement code (like OP posted) recalculates a multiplier once each loop. Then all of your values are merely multiplied with that 'time correcting' multiplier.

So for example. You have to move objects twice as far at 30fps as you do at 60fps. So if you have Move Object objectid, 10 * timemultiply... Then timemultiply will be twice as big at 30fps as it is at 60fps. It will be some odd middle value no matter the frame rate to make that movement grow or shrink to keep the object moving at the right speed on screen.

Ortu
DBPro Master
16
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 24th Jun 2015 19:47 Edited at: 24th Jun 2015 19:51
I don't mean I make a bunch of function calls, I mean that I adjust based on a desired value per second (in the case below, 55 units per second at maximum walking speed) against the time elapsed since the last update.

regardless of framerate, this ensures that if 1 second has passed the character will be moved 55 units. if 0.5 seconds passsed, 27.5 units, if 10 seconds passed 550 units and so on. It doesn't attempt to smooth the movement and can create jumps at very low framerates, but it does keep the distance:time ratio constant


quick cutdown to relevant bits. the update function is called once per main loop



Chris Tate
DBPro Master
15
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 28th Jun 2015 16:28
In addition to what has been contributed by the other guys, you can use some of my basic functions for movement and value adjustment over time. The simplicity of the functions I provided here make them as a complement for any time based system you take on board.

Mage
17
Years of Service
User Offline
Joined: 3rd Feb 2007
Location: Canada
Posted: 30th Jun 2015 10:36 Edited at: 30th Jun 2015 10:36
Quote: "I don't mean I make a bunch of function calls, I mean that I adjust based on a desired value per second (in the case below, 55 units per second at maximum walking speed) against the time elapsed since the last update.

regardless of framerate, this ensures that if 1 second has passed the character will be moved 55 units. if 0.5 seconds passsed, 27.5 units, if 10 seconds passed 550 units and so on. It doesn't attempt to smooth the movement and can create jumps at very low framerates, but it does keep the distance:time ratio constant


quick cutdown to relevant bits. the update function is called once per main loop

+ Code Snippet"


You can get away with doing this. It's not that it's wrong, it's more a situation where you aren't building in scalability into your design.

It works for that example. But if you had to make those calculations in a larger project where the calculations needed to be made in many different functions, the approach would become ugly.

In simplest terms Chars(c).baseData.elapsed should be calculated once on each frame and accessible globally. Then no matter where you are, the physics code, the ai routines, menu functions, etc you are not constantly tracking and recalculating the value.

You get a simple clean consistent variable that everything uses. You use less code. There's one place to to make changes. And really cool... 1 place to make tweaks like bullet time by doing things like halving or quartering that value at calculation time.

thenerd
15
Years of Service
User Offline
Joined: 9th Mar 2009
Location: Boston, USA
Posted: 7th Jul 2015 06:25
My TBM Module that I use for everything.

Call TBM_Init() at the beginning of your code.
Call TBM_Update() each sync frame.
Multiply all movement by "TBM".
Use TBM_SetTimerScale(scale) to create slow motion.





Mage
17
Years of Service
User Offline
Joined: 3rd Feb 2007
Location: Canada
Posted: 7th Jul 2015 20:13
You can change:
TBM = Diff# / 10.0

To

TBM = Diff#

Since the division is pointless.


if TBM>10 then TBM=10


Should be changed to

if TBM>1000 then TBM=0

If the first line above is altered.


Basically if there is a huge lag spike that lowers the frame rate to lower than 1 fps, instead of cutting off the correction value at some wrong arbitrary value you just set it to 0.

Using a cutoff like that is a good idea since it prevents lag spikes from teleporting the player through walls and etc.

Login to post a reply

Server time is: 2024-04-25 15:40:02
Your offset time is: 2024-04-25 15:40:02