Sign in to follow this  

How do I make time based movement

This topic is 4491 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Express every speed or acceleration (linear and/or angular) in units per time.


Example: speed = 1m / sec
or speed = 1 cubit/ minute
or speed = 7miles/hour


It does not matter: you have unit/time

Then you need a timer.

Search in the forum you will find a lot of threads about.
You can use timeGetTime() under windoz if you dont need extreme precision (~10ms).

To compute the new position in the next frame multiply the elapsed time for your speed and you have the space.


// frame
....
static float previous_time = timeGetTime();
float speed = 1; // 1 unit/second
static float position = 0;
float current_time = timeGetTime();
float elapsed_time = (current_time - previous_time)/1000; // [ms] -> [s]

position += speed * elapsed_time; // update

previous_time = current_time; // update
...




In practice your speed could be in vectorial form

speed = Vector (Vx, Vy, Vz)

but the idea is the same.



Share this post


Link to post
Share on other sites
But where would I put that. For example:


PSEUDO CODE

main loop
{
DrawMap();
UpdateMovement();
}



because I want to update movement only every lets say 10 miliseconds. So if I use the previous and current time thing you showed, my previous would be updateed each time, even if the difference between previous and current is not 10 miliseconds. I would never reach 10 miliseconds and my code would be stuck! I might be wrong, so please prove me wrong. Thanks for the above help anyways.

Share this post


Link to post
Share on other sites
You'd want to definately test for >= 10ms. The chances of hitting exactly 10ms is very slim as you point out.

I don't know why you'd want to do such specific time steps -- that just sounds like you're making it framerate dependant like you are trying to avoid. If I were you, I'd just update it based on the time elapsed since the previous frame (as the poster above mentioned). This is how you make it framerate independant.

Here is a sample bit of code to show how I handle my movement in nearly every case (simplified quite a bit for readability).

// This is the bit of code that runs each frame
GameLoop()
{
// Find the time elapsed since last frame (m_fPrevTime is a member var
// or static or whatever to make it persist between frames)
float fCurrTime = timeGetTime();
float fTimeElapsed = fCurrTime - m_fPrevTime;
// fTimeElapsed *= 0.001f; // Run this line only if you want your result in seconds

// Iterate through each object and update
for( /* iterate through list of objects */ )
pObject->Update( fTimeElapsed );

m_fPrevTime = fCurrTime;
}

void Object::Object( vector vPos, vector vDir, float fSpeed )
{
m_vForces(0.0f,0.0f,0.0f);
m_vAcceleration(0.0f,0.0f,0.0f);
m_vVelocity = vDir * fSpeed;
m_vPos = vPos;
}

void Object::Update( float fDt )
{
m_vAcceleration += m_vForces * fDt;
m_vVelocity += m_vAcceleration * fDt;
m_vPos += m_vVelocity * fDt;
}



I almost never use the forces and acceleration components as constant velocity is most common for me. But you could make acceleration be gravity and forces be wind or something like that. This will work the same for both two and three dimensions.

Share this post


Link to post
Share on other sites
Quote:
Original post by AdamGL
But where would I put that. For example:

*** Source Snippet Removed ***

because I want to update movement only every lets say 10 miliseconds. So if I use the previous and current time thing you showed, my previous would be updateed each time, even if the difference between previous and current is not 10 miliseconds. I would never reach 10 miliseconds and my code would be stuck! I might be wrong, so please prove me wrong. Thanks for the above help anyways.


One frame you will use 10 ms, the next, say, 5 ms then 2 ms (note also that you get the average since you compute a difference between absolute values).
This is how an animation works...[smile]
You dont know when you update the scene but when you update it you use the right elapsed time and move objects accordingly.

If you prefer a time based update (different than time based movement) you can derive an alarm from your timer class and write something like this

if (elapsed_time > 10ms) render_new_frame();

but be warned! You need a more precise timer to do this ( for example QueryPerformanceCounter() ) but I dont see the benefit .

Share this post


Link to post
Share on other sites
To helix
Quote:


void Object::Update( float fDt ){
m_vAcceleration += m_vForces * fDt;
m_vVelocity += m_vAcceleration * fDt;
m_vPos += m_vVelocity * fDt;
}



The code, from a physic point of view, is meaningless.
It's more correct to write
acceleration = k*force (who remember F = ma ?)
where k can be the inverse of the mass or something simulating it.

This method works if you dont need precise results but simply a nice result.

Share this post


Link to post
Share on other sites
Thanks guys, I finally got it. I kept screwing around with the "loop till its time" thing and that was bull, so thanks for putting me in the right direction! Oh by the way if you guys know any internet resources that teach vectors and stuff like that, could you post them, because I know I need to learn these things soon to keep programming and I haven't learned it in school yet(grade 9). Thanks for the help! :)

Share this post


Link to post
Share on other sites
Quote:
Original post by blizzard999
To helix
The code, from a physic point of view, is meaningless.
It's more correct to write
acceleration = k*force (who remember F = ma ?)
where k can be the inverse of the mass or something simulating it.

This method works if you dont need precise results but simply a nice result.


I certainly wouldn't call it meaningless because it works quite nicely. But if you want to throw mass into the equation, by all means, add that in. There are always some tweaks for any situation. As far as games are concerned, isn't a nice result what we're looking for? If you're going to make a racing sim for example, you probably wouldn't be doing movement this way at all in favor of something vastly more complex and precise.

Share this post


Link to post
Share on other sites
What blizzard999 is saying is that the line

m_vAcceleration += m_vForces * fDt;
is wrong. A constant force produces a constant acceleration, but in your code a constant force produces a changing acceleration. The correct code would be:
    m_vAcceleration = m_vForces / mass; 


It should also be noted that if the acceleration is not 0, then there can be enough error in the computation to cause problems (the motion changes depending on the frame rate). When the acceleration is constant (such as simple gravity), the following algorithm produces error-free results:
    v0 = v;
d0 = d;
v = v0 + a * dt;
d = d0 + v0 * dt + 0.5f * a * dt * dt;
If acceleration is not constant, then you should use a more advanced method of integration such as RK4 or verlet.

Share this post


Link to post
Share on other sites
I thought that was vertlet integration that I was using?

Well, I guess you got me there. To be honest, I've never included the acceleration or forces in my code -- I just threw it in there to be complete. I only use velocity and position...and occasionally gravity. I thought you were referring to my method of integration as a whole.

Share this post


Link to post
Share on other sites
Keep in mind that if you want the option to Replay the game (a la Age of Empires), where you can see all your units moving as you moved them when you just played, you're going to have to define a minimum time-step. This is to synchronise the input with the time, so that you get reliable replay, or something. I read about it here a few years ago.

Share this post


Link to post
Share on other sites

This topic is 4491 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this