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 / Delta time problem - need maths help.

Author
Message
Ric
21
Years of Service
User Offline
Joined: 11th Jul 2004
Location: object position x
Posted: 27th Dec 2004 05:37
Hope everyone had a great Christmas.

Anyone here able to help me with a maths problem? Then bare with me - long post ahead .....

I'm using the delta-time principle in order to make my program run at a constant speed regardless of the processor speed. I understand the basic concept - 'delta time, or dt# is the time for one program loop. Then, when any variable is changed by a certain increment (or decrement), it is multiplied by dt#. (Integrating between two values, in mathemeatical terms.)

For example, if an object is being moved by 2 each loop, then I have:

move object 1,2*dt#

That works fine when the variable is changing linearly like that.

Here's the problem:

What do you do when you want to scale a variable by a set amount each loop? For example, I have a velocity v#, and each loop I want to multiply it by 0.99, which is the friction. So I have:

v#=v#*0.99

But how do I incorporate the dt#? It doesn't work if you multiply it by dt#, as it did for incremental values. (I've tested the program using different sync rates, and timed certain events to try and get consistency). I tried raising the 0.99 to the power of dt# too, and that didn't work either.

Anyone who knows - I'd be really appreciative as I've been stuck on this for two days!


Lost in Thought
22
Years of Service
User Offline
Joined: 4th Feb 2004
Location: U.S.A. : Douglas, Georgia
Posted: 27th Dec 2004 06:31 Edited at: 27th Dec 2004 07:42
I don't think I am understanding you correctly. You want to do something like

v# = v#*0.99*dt# ?

You want to scale v# by 0.99 but only the amount it would scale by dt#?

Perhaps you could make a small code showing how you intend to use v# exactly.

[edit] Or do you mean like you want to scale v# by a total of 0.99 every second scaling it each loop?
Change the sync rate and observe the values.

the value for 10 seconds of deceling at 0.99 per seond should be around 904.382075 gotten from

It will obviosly be further off at lower frames per second because there will be no loop time exactly near 10 secs but at 100 fps it is really close. At 1 FPS it is less because the time nearest but over 10 secs is 10.8 and it decelled an extra .8 secs. I'm sure there may be an easier way I'm just no good with advanced maths. I like to break it down to what I know.

Tamandt
21
Years of Service
User Offline
Joined: 23rd Dec 2004
Location:
Posted: 27th Dec 2004 06:33
Wouldnt setting the max frame rates be a whole lot simpler?
Hamish McHaggis
23
Years of Service
User Offline
Joined: 13th Dec 2002
Location: Modgnik Detinu
Posted: 27th Dec 2004 07:27 Edited at: 27th Dec 2004 07:32
With changing values, use the equations...

pos = pos + (vel*dt) + (accel*dt*dt)
vel = vel + (accel*dt)

Making sure you change the position before the velocity (if you want to be really fussy, but if you have a high enough frame rate it won't make too much difference).

This obviously won't work when you scale the value by multiplying it by a constant, but that's not how friction works anyway (or so I think), surface friction is a constant force no matter what the velocity is. Air resistance however is another story, the general rule for it I think is friction = vel*vel*const.

As for the solution to the way you mentioned, we did the equation for that in maths not too long ago, but I can't find my notes (probably cos I didn't take any ).

Isn't it? Wasn't it? Marvellous!
Tamandt
21
Years of Service
User Offline
Joined: 23rd Dec 2004
Location:
Posted: 27th Dec 2004 08:09
I am extremely curious here. But if you write a program and limit it to 60 framers per second, then why would you need to do more than that. I mean wouldnt a p4 3GHz draw 600 frames in ten seconds and a future 100THz cpu draw 600 frames in ten seconds?

I remember older games i played that run to fast to be played on modern Pc's but that is because they werent limiting FPS. Even NES Emulators run thousands of frames per second, but limit it to a virtual 60 FPS. You can incraase this (speed of game increases) or deacrease it and the speed of game will follow.

So how come this delta time in needed then?
Ric
21
Years of Service
User Offline
Joined: 11th Jul 2004
Location: object position x
Posted: 27th Dec 2004 22:41
@Lost - yes, I think you have the idea - I want v# to decrease exponentially - ie start off decreasing in big steps but going down in smaller and smaller steps as the value of v# gets smaller. So I'm doing this by saying v#=v#*0.99 each loop. (The value 0.99, by the way, represents the damping applied to the motion of a wave particle, but that's not important). The value 0.99 is also very sensitive - a bit too high or a bit too low and the motion is all wrong.

So, for an initial value of v#=1000, I have the value going 1000,990,980.1,etc..... as you showed with your example.

Now, I got that value of 0.99 by trial and error - ie, on my computer it provides the right amount of damping. However, when I set the sync rate much lower, the damping isn't applied as quickly, because v# gets multiplied by 0.99 less frequently. So, the question is, if I have the loop time dt#, what is the equation which incorporates the value of dt# into v#=v#*0.99, so that the value of v# changes by the same amount regardless of sync rate?

I know that for linear decrements, it would be

v#=v#-constant*dt#

but for non linear decrements,

v#=v#*contant*dt# doesn't work.

nor does v#=v#*constant^dt#

nor does v#=v#/(2^dt#) (yes, I was trying pretty much anything!)

Anyone know?

@ Tamant: Fine if you want to limit the max fps, (ie the user has a faster computer than you do) but what if the user's computer runs slower than the desired fps? You can't force the fps to a higher value using sync rate - so it has to be done using delta time.

@Hamish: yes - linear changes like surface friction I'm fine with. It's the non linear ones I'm struggling with.


Hamish McHaggis
23
Years of Service
User Offline
Joined: 13th Dec 2002
Location: Modgnik Detinu
Posted: 27th Dec 2004 23:58 Edited at: 28th Dec 2004 00:01
v#=v#*constant^dt#

Should work. Look at this simple demo.



All the delta time constants add up to 1, and the end result is always the same. You can see why it does if you use the rule of indices that (x^y)^z = x^(y*z) .

However, if you're adjusting a position variable by the velocity variable, then that's why you're having the problems. If you change your method to the way I mentioned before then I can help you, but I will think about a way to do it for the way you are doing it.

Isn't it? Wasn't it? Marvellous!
tiresius
23
Years of Service
User Offline
Joined: 13th Nov 2002
Location: MA USA
Posted: 28th Dec 2004 00:38
Quote: "But if you write a program and limit it to 60 framers per second, then why would you need to do more than that."


That's only half of it. You can just limit your game to 60 FPS, but that causes the entire game to run slow on a slower machine that can only achieve 30 FPS. Using timer-based movement helps prevent this from happening and makes your game playable no matter what speed the PC is at.
David T
Retired Moderator
23
Years of Service
User Offline
Joined: 27th Aug 2002
Location: England
Posted: 28th Dec 2004 01:58 Edited at: 28th Dec 2004 02:01
This is a function I use:



so if your player moves at 10 units per second at 60fps, then at 30fps scale# is 2 and so the player'd move at 20 units per second.

This way really high frame rates just mean the player moves less each loop - but to the eye the player always moves the same amount.

Incorporating this into your problem with having a velocity - I assume you just scale down the velocity?

Get 15 new commands, all the date / time commands left out of DBPro for free!
DOWNLOAD PLUGINS HERE: http://www.davidtattersall.me.uk/ and select "DarkBasic"
Hamish McHaggis
23
Years of Service
User Offline
Joined: 13th Dec 2002
Location: Modgnik Detinu
Posted: 28th Dec 2004 02:06 Edited at: 28th Dec 2004 02:22
Ok, I think I've worked it out. We've already got the equation for finding velocity...

vel = vel * const ^ dt

But finding the position is the problem, as you've probably found out (I presume thats the problem, cos the above is the correct equation unless I'm completely mistaken).

If you've done physics you'll know that the area under a velocity-time graph is the dispacement. If you haven't, take my word on it.

If you've done integration of y = a^x with respect to x (ie. x changes, a is constant), then you'll know that the integral of c*a^x with respect to x, is...

(c*a^x)/(ln a), where x > 0 and x <> 1

The integral between 0 and x (y isn't 0 at x = 0, so we have to integrate between two points) is the area beneath graph (I'm assuming you haven't done integration at the moment), and the area beneath our graph (vel = vel * const ^ dt) is the displacement, which is what we want. So integrating our graph, we get...

disp = (vel*const^dt)/(ln const) - (vel/(ln const))
pos = pos + disp
vel = (vel*const^dt)

By the way, ln is just natural log. Since const is constant, you can find out its natural log using a calculator and place it at the top of your program (unless there is a dll I don't know about that has a natural log function I don't know about).

As you can see in this demo, it seems to work.



Hope I helped, and to be honest, you don't really need to know why it works .

Isn't it? Wasn't it? Marvellous!
Ric
21
Years of Service
User Offline
Joined: 11th Jul 2004
Location: object position x
Posted: 28th Dec 2004 03:01
Thanks guys - a couple of methods for me to try out - I'll let you know if it works!


Ric
21
Years of Service
User Offline
Joined: 11th Jul 2004
Location: object position x
Posted: 29th Dec 2004 00:48
OK - a day later, and I'm further, but not there yet.

Dave - on closer inspection, your function which divides by the fps does pretty much the same thing as multiplying by dt# (the loop time). Still get the same problem when scaling exponentially though.

Hamish - you are clearly a very clever person! I can see that what you said is right, because your demo code works. Somehow I knew it was going to involve logs. By the way, here is a function that calculates natural logs :


However, when implemented into my code, the velocity of the wave particle gets larger as the frame rate gets lower - could it be because of the accleration variable I've also got?

In my code I have:

velocity=velocity+acceleration
position=position+velocity
velocity=velocity*damping

Now, I've applied your maths to the second two lines just as you did in your demo code, but what do I do to the first line, where there is an acceleration applied to the velocity? I tried doing this:



But that must be wrong because it doesn't work! I know that the velocity is found by integrating the acceleration, and the position is found by integrating the velocity - but I get stuck around there ......

Please don't give up on me yet - I think we're close!!


Hamish McHaggis
23
Years of Service
User Offline
Joined: 13th Dec 2002
Location: Modgnik Detinu
Posted: 29th Dec 2004 02:40
Hmmm, now you're making it complicated. You can use the method I stated first of all for acceleration, and you can use the one above for scaling, but if you use both scaling and acceleration, unfortunately you can't just combine both equations, as both acceleration and scaling are constant, and acceleration means that the velocity is constantly changing, and therefore the scaling constant isn't going to be straightforward. I'll try and figure something out.

Isn't it? Wasn't it? Marvellous!
Ric
21
Years of Service
User Offline
Joined: 11th Jul 2004
Location: object position x
Posted: 29th Dec 2004 04:40
Thanks I'm sure if you can work out an answer to this one it will be useful for others as well, like for applying air resistance to an accelerating object for example. Didn't think it would get this tricky though!! Perhaps we're overlooking a simpler way of keeping the program run consistently at different speeds .....


Hamish McHaggis
23
Years of Service
User Offline
Joined: 13th Dec 2002
Location: Modgnik Detinu
Posted: 29th Dec 2004 19:41 Edited at: 29th Dec 2004 19:41
Ok, I've done some research, and found an article on integration in game physics. It tells about the RK4 integrator, which does look to be a better solution to your problem. It apparently isn't as accurate as the methods above, but it can deal with fluxuations and inconsistancys in the physics. I'm currently trying to get an example working in darkbasic, so hang tight .

http://gaffer.org/articles/Integration.html

Isn't it? Wasn't it? Marvellous!
Hamish McHaggis
23
Years of Service
User Offline
Joined: 13th Dec 2002
Location: Modgnik Detinu
Posted: 29th Dec 2004 21:20 Edited at: 29th Dec 2004 21:44
Ok, I spent some time looking at that article, and have come up with this demo. If has time based physics, with spring forces, damping, air resistance and simple forces, but only in one dimension, although two dimensions would be very much possible, if they were independent of each other, you could just stick two calls to integrate() in, but if they are dependent on each other, you'll have to put two dimensional functionality into the functions (not forgetting to use the total displacement with spring constants and such, using pythagorus (x^2 = y^2 + z^2))

Use code snippet button, not code box...



Isn't it? Wasn't it? Marvellous!
Ric
21
Years of Service
User Offline
Joined: 11th Jul 2004
Location: object position x
Posted: 30th Dec 2004 02:25
Brilliant


This is pretty deep! I'm going to try putting this into my program tonight. As far as I can tell, then, the RK4 integration method gives far more accurate results than Euler integration - eg x=x+v*dt. (Didn't even know that's what it was called!) This is great, as part of the problem I was having is that the damping constants needed to be extremely precise - eg 4 decimal places, to prevent my variables tending to zero or exploding - and small inaccuracies when converting damping constants for different loop times were having catastrophic effects.)

However, the other thing I noticed is that, the main problem I was having was in the scaling of a variable. I was calculating the velocity according to the acceleration and then recalculating the velocity according to the damping (ie v=v*damping), but it makes far more sense to apply the damping as a force which affects the resultant force BEFORE the velocity is calculated, (ie force=restoring force-damping force, and then a=force/mass) which means damping is not loop time dependent, and I don't need to worry about the scaling problem. Horrah!! Nevertheless, I'm worried that one day I will need to do something like v=v*scalefactor, and I'm really not sure what I would do if an Euler integration wasn't accurate enough. Anyway, I worry too much!

Thanks a million for your help Hamish - you are the Maths Man!!


Hamish McHaggis
23
Years of Service
User Offline
Joined: 13th Dec 2002
Location: Modgnik Detinu
Posted: 30th Dec 2004 02:37
Quote: "Nevertheless, I'm worried that one day I will need to do something like v=v*scalefactor, and I'm really not sure what I would do if an Euler integration wasn't accurate enough. Anyway, I worry too much!"


Well, if you're doing realistic physics simulations, you won't need to, as that isn't how it works in real life. Anyway, if you need to do something like that, so long as you're not doing anything else, just use the previous equation...

disp = (vel*const^dt)/(ln const) - (vel/(ln const))
pos = pos + disp
vel = (vel*const^dt)

Isn't it? Wasn't it? Marvellous!
Ric
21
Years of Service
User Offline
Joined: 11th Jul 2004
Location: object position x
Posted: 30th Dec 2004 03:47 Edited at: 30th Dec 2004 04:09
Quote: "Well, if you're doing realistic physics simulations, you won't need to, as that isn't how it works in real life."


Interesting point - and one that got me thinking .... I can think of a few physics examples where a constant scale factor would be applied - radioactive decay for one. Then I thought, how do you calculate the activity of a substance at a certain point in time? A=A*e^kt. In other words, it's another solution to the scaling problem - where t is either the total time elapsed since the initial value of A, or the loop time since the previous value of A, and where k is the decay constant. Should work too, shouldn't it?


Hamish McHaggis
23
Years of Service
User Offline
Joined: 13th Dec 2002
Location: Modgnik Detinu
Posted: 30th Dec 2004 04:24
When I said physics, I meant mechanics . Of course you would use it in radioactive decay, but the number of leftover atoms isn't velocity, you don't move stuff by the number of atoms. You probably wouldn't even need e. You'd just do this wouldn't you?

Ae = As*k^t

Where Ae is the end amount of atoms, As is the start amount of atoms, k is the radioactive decay per unit t, and t is the time since the start of the simulation.

Isn't it? Wasn't it? Marvellous!
Ric
21
Years of Service
User Offline
Joined: 11th Jul 2004
Location: object position x
Posted: 30th Dec 2004 04:48
Yeah - unfortunately, I just tried it, and it didn't give good accuracy at different frame rates:

this changes an initail value according to the total time elapsed:



or this one changes the previous value by the previous loop time:



Testing for different sync rates gives different answers for sync rates below 20ish.

Can't really think why, but I guess your way works anyway so I'm not too worried. And as for the 'e', I think that's important for getting a 'natural' shape for the exponential curve, ... I vaguely remember reading an article once on the significance of natural logs as opposed to other bases. Anyway - sliding off topic!

Thanks again for your help - I'll know where to ask in future when I get maths headaches!!


Login to post a reply

Server time is: 2026-06-09 14:57:28
Your offset time is: 2026-06-09 14:57:28